Merge branch 'master' into pc98x1

This commit is contained in:
TC1995
2025-03-26 19:24:31 +01:00
171 changed files with 12446 additions and 5385 deletions

View File

@@ -144,6 +144,18 @@ else()
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
option(AUDIO4 "Use audio(4) as sound backend" ON)
else()
set(AUDIO4 OFF)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
option(SNDIO "Use sndio as sound backend" ON)
else()
set(SNDIO OFF)
endif()
if(WIN32)
set(QT ON)
option(CPPTHREADS "C++11 threads" OFF)

View File

@@ -32,6 +32,7 @@
#include <wchar.h>
#include <stdatomic.h>
#include <unistd.h>
#include <math.h>
#ifndef _WIN32
# include <pwd.h>
@@ -172,7 +173,6 @@ int force_43 = 0; /* (C) video *
int video_filter_method = 1; /* (C) video */
int video_vsync = 0; /* (C) video */
int video_framerate = -1; /* (C) video */
char video_shader[512] = { '\0' }; /* (C) video */
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of
pass-through for serial ports */
int bugger_enabled = 0; /* (C) enable ISAbugger */
@@ -214,6 +214,7 @@ int hook_enabled = 1; /* (C) Keyboar
int test_mode = 0; /* (C) Test mode */
char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */
int sound_muted = 0; /* (C) Is sound muted? */
int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */
int other_ide_present = 0; /* IDE controllers from non-IDE cards are
present */
@@ -233,6 +234,8 @@ extern int CPUID;
extern int output;
int atfullspeed;
extern double exp_pow_table[0x800];
char exe_path[2048]; /* path (dir) of executable */
char usr_path[1024]; /* path (dir) of user data */
char cfg_path[1024]; /* full path of config file */
@@ -252,6 +255,8 @@ int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
int efscrnsz_y = SCREEN_RES_Y;
#endif
__thread int is_cpu_thread = 0;
static wchar_t mouse_msg[3][200];
static volatile atomic_int do_pause_ack = 0;
@@ -435,6 +440,75 @@ fatal_ex(const char *fmt, va_list ap)
fflush(stdlog);
}
/* Log a warning error, and display a UI message without exiting. */
void
warning(const char *fmt, ...)
{
char temp[1024];
va_list ap;
char *sp;
va_start(ap, fmt);
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
va_end(ap);
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL)
*sp = '\0';
do_pause(2);
ui_msgbox(MBX_ERROR | MBX_ANSI, temp);
fflush(stdlog);
do_pause(0);
}
void
warning_ex(const char *fmt, va_list ap)
{
char temp[1024];
char *sp;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL)
*sp = '\0';
do_pause(2);
ui_msgbox(MBX_ERROR | MBX_ANSI, temp);
fflush(stdlog);
do_pause(0);
}
#ifdef ENABLE_PC_LOG
int pc_do_log = ENABLE_PC_LOG;
@@ -1084,6 +1158,11 @@ pc_init_modules(void)
machine_status_init();
for (c = 0; c <= 0x7ff; c++) {
int64_t exp = c - 1023; /* 1023 = BIAS64 */
exp_pow_table[c] = pow(2.0, (double) exp);
}
if (do_nothing) {
do_nothing = 0;
exit(-1);

View File

@@ -23,8 +23,6 @@ endif()
add_executable(86Box
86box.c
config.c
log.c
random.c
timer.c
io.c
acpi.c
@@ -41,15 +39,11 @@ add_executable(86Box
pci.c
mca.c
usb.c
fifo.c
fifo8.c
device.c
nvr.c
nvr_at.c
nvr_ps2.c
machine_status.c
ini.c
cJSON.c
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -106,7 +100,11 @@ if(INSTRUMENT)
endif()
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd
net print scsi sio snd vid voodoo plat ui)
net print scsi sio snd utils vid voodoo plat ui)
if(HAIKU)
target_link_libraries(86Box be)
endif()
if(WIN32 AND ARCH STREQUAL "i386")
if(MINGW)
@@ -252,7 +250,9 @@ add_subdirectory(printer)
add_subdirectory(sio)
add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(utils)
add_subdirectory(video)
if (APPLE)
add_subdirectory(mac)
endif()
@@ -263,3 +263,7 @@ else()
add_compile_definitions(USE_SDL_UI)
add_subdirectory(unix)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
add_custom_command(TARGET 86Box POST_BUILD COMMAND paxctl ARGS +m $<TARGET_FILE:86Box> COMMENT "Disable PaX MPROTECT")
endif()

View File

@@ -211,7 +211,10 @@ acpi_update_irq(acpi_t *dev)
if ((dev->regs.pmcntrl & 0x01) && sci_level) switch (dev->irq_mode) {
default:
picintlevel(1 << dev->irq_line, &dev->irq_state);
if (dev->irq_line != 0)
picintlevel(1 << dev->irq_line, &dev->irq_state);
else
dev->irq_state = 1;
break;
case 1:
pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state);
@@ -223,7 +226,10 @@ acpi_update_irq(acpi_t *dev)
break;
} else switch (dev->irq_mode) {
default:
picintclevel(1 << dev->irq_line, &dev->irq_state);
if (dev->irq_line != 0)
picintclevel(1 << dev->irq_line, &dev->irq_state);
else
dev->irq_state = 0;
break;
case 1:
pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state);

File diff suppressed because it is too large Load Diff

View File

@@ -409,7 +409,7 @@ image_get_track_and_index(const cd_image_t *img, const uint32_t sector,
for (int i = 0; i < img->tracks_num; i++) {
track_t *ct = &(img->tracks[i]);
for (int j = 0; j < 3; j++) {
if ((ct->point >= 1) && (ct->point <= 99)) for (int j = 0; j < 3; j++) {
track_index_t *ci = &(ct->idx[j]);
if ((ci->type >= INDEX_ZERO) && (ci->length != 0ULL) &&
((sector + 150) >= ci->start) && ((sector + 150) <= (ci->start + ci->length - 1))) {

View File

@@ -53,6 +53,7 @@
#define REG_RA1 0x61 /* Command Delay */
#define RA1_MASK 0xff /* 1111 1111 */
#define RA1_MASK_SX 0xbf /* 1X11 1111 */
#define RA1_BUSDLY 0x03 /* AT BUS command delay */
#define RA1_BUSDLY_SH 0
#define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */
@@ -81,6 +82,7 @@
#define ATWS_3 1 /* 3 wait states */
#define ATWS_4 2 /* 4 wait states */
#define ATWS_5 4 /* 5 wait states */
#define RA2_387SX 0x80
/* CS8221 82C212 controller registers. */
#define REG_RB0 0x64 /* Version ID */
@@ -103,6 +105,9 @@
#define REG_RB2 0x66 /* Memory Enable 1 */
#define RB2_MASK 0x80 /* 1XXX XXXX */
#define RB2_MASK_SX 0xe0 /* 111X XXXX */
#define RB2_BOT256 0x20 /* bottom 256K is on sysboard (1) */
#define RB2_MID256 0x40 /* middle 256K is on sysboard (1) */
#define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */
#define REG_RB3 0x67 /* Memory Enable 2 */
@@ -198,6 +203,7 @@
#define REG_RB12 0x6f /* Miscellaneous */
#define RB12_MASK 0xe6 /* 111R R11R */
#define RB12_MASK_SX 0xf6 /* 1111 R11R */
#define RB12_GA20 0x02 /* gate for A20 */
#define RB12_RASTMO 0x04 /* enable RAS timeout counter */
#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */
@@ -221,11 +227,10 @@ typedef struct ram_page_t {
} ram_page_t;
typedef struct neat_t {
uint8_t mem_flags[32];
uint8_t mem_flags[64];
uint8_t regs[128]; /* all the CS8221 registers */
uint8_t indx; /* programmed index into registers */
char pad;
uint8_t sx;
uint16_t ems_base; /* configured base address */
uint32_t ems_frame; /* configured frame address */
@@ -238,8 +243,19 @@ typedef struct neat_t {
ram_page_t shadow[32]; /* Shadow RAM pages */
} neat_t;
static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0xfe, 0x00, 0x00,
0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 };
static uint8_t defaults[2][16] = { { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0x0e, 0x00, 0x00,
0x00, 0x00, 0x80, 0x43, 0x10, 0x00, 0x00, 0x12 },
{ 0x0a, 0x45, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00,
0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x00, 0x08 } };
static uint8_t reg_masks[2][16] = { { RA0_MASK, RA1_MASK, RA2_MASK, 0x00,
RB0_MASK, RB1_MASK, RB2_MASK, RB3_MASK,
RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK,
RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK },
{ RA0_MASK, RA1_MASK_SX, RA2_MASK, 0x00,
RB0_MASK, RB1_MASK, RB2_MASK_SX, RB3_MASK,
RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK,
RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK_SX } };
static uint8_t masks[4] = { RB10_P0EXT, RB10_P1EXT, RB10_P2EXT, RB10_P3EXT };
static uint8_t shifts[4] = { RB10_P0EXT_SH, RB10_P1EXT_SH, RB10_P2EXT_SH, RB10_P3EXT_SH };
@@ -405,12 +421,12 @@ ems_writew(uint32_t addr, uint16_t val, void *priv)
static void
neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask)
{
if ((addr >= 0x00080000) && (addr < 0x00100000) &&
((new_flags ^ dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) {
dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask;
dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags;
if ((addr < 0x00100000) &&
((new_flags ^ dev->mem_flags[addr / EMS_PGSIZE]) & mask)) {
dev->mem_flags[addr / EMS_PGSIZE] &= ~mask;
dev->mem_flags[addr / EMS_PGSIZE] |= new_flags;
new_flags = dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE];
new_flags = dev->mem_flags[addr / EMS_PGSIZE];
if (new_flags & MEM_FLAG_ROMCS) {
neat_log("neat_mem_update_state(): %08X-%08X: %02X (ROMCS)\n", addr, addr + size - 1, new_flags);
@@ -670,9 +686,10 @@ remap_update(neat_t *dev, uint8_t val)
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, dev->remap_base << 10);
if (dev->remap_base > 1024) {
uint32_t base = (val & RB7_EMSEN) ? (0x00100000 + (dev->ems_size << 10)) : 0x00100000;
mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (dev->remap_base << 10) - 0x00100000);
mem_mapping_set_exec(&ram_high_mapping, &(ram[(val & RB7_EMSEN) ? 0x00100000 :
(0x00100000 + (dev->ems_size << 10))]));
mem_mapping_set_exec(&ram_high_mapping, &(ram[base]));
} else
mem_mapping_disable(&ram_high_mapping);
@@ -691,6 +708,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
uint8_t xval;
uint8_t j;
uint8_t *reg;
uint8_t mask;
int i;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
@@ -705,10 +723,11 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case 0x23:
reg = &dev->regs[dev->indx];
xval = *reg ^ val;
mask = reg_masks[dev->sx][dev->indx & REG_MASK];
switch (dev->indx) {
case REG_RA0:
val &= RA0_MASK;
*reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH);
val &= mask;
*reg = (*reg & ~mask) | val | (RA0_REV_ID << RA0_REV_SH);
if ((xval & 0x20) && (val & 0x20))
outb(0x64, 0xfe);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
@@ -717,32 +736,32 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RA1:
val &= RA1_MASK;
*reg = (*reg & ~RA1_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RA2:
val &= RA2_MASK;
*reg = (*reg & ~RA2_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RB0:
val &= RB0_MASK;
*reg = (*reg & ~RB0_MASK) | val | (RB0_REV_ID << RB0_REV_SH);
val &= mask;
*reg = (*reg & ~mask) | val | (RB0_REV_ID << RB0_REV_SH);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RB1:
val &= RB1_MASK;
*reg = (*reg & ~RB1_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
shadow_recalc(dev);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg);
@@ -750,20 +769,37 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB2:
val &= RB2_MASK;
*reg = (*reg & ~RB2_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
if (dev->sx) {
if (val & RB2_BOT256)
neat_mem_update_state(dev, 0x00000000, 0x00040000,
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
else
neat_mem_update_state(dev, 0x00000000, 0x00040000,
0x00, MEM_FMASK_SHADOW);
if (val & RB2_MID256)
neat_mem_update_state(dev, 0x00040000, 0x00040000,
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
else
neat_mem_update_state(dev, 0x00040000, 0x00040000,
0x00, MEM_FMASK_SHADOW);
}
if (val & RB2_TOP128)
neat_mem_update_state(dev, 0x00080000, 0x00020000, MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
neat_mem_update_state(dev, 0x00080000, 0x00020000,
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
else
neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, MEM_FMASK_SHADOW);
neat_mem_update_state(dev, 0x00080000, 0x00020000,
0x00, MEM_FMASK_SHADOW);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RB3:
val &= RB3_MASK;
*reg = (*reg & ~RB3_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
shadow_recalc(dev);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg);
@@ -771,8 +807,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB4:
val &= RB4_MASK;
*reg = (*reg & ~RB4_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
shadow_recalc(dev);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg);
@@ -780,8 +816,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB5:
val &= RB5_MASK;
*reg = (*reg & ~RB5_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
shadow_recalc(dev);
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg);
@@ -789,20 +825,20 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB6:
val &= RB6_MASK;
*reg = (*reg & ~RB6_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RB7:
val &= RB7_MASK;
val &= mask;
if (xval & (RB7_EMSEN | RB7_UMAREL))
remap_update(dev, val);
dev->regs[REG_RB7] = val;
*reg = (*reg & ~mask) | val;
if (xval & RB7_EMSEN)
ems_remove_handlers(dev);
@@ -816,16 +852,16 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB8:
val &= RB8_MASK;
*reg = (*reg & ~RB8_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg);
#endif
break;
case REG_RB9:
val &= RB9_MASK;
*reg = (*reg & ~RB9_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg);
#endif
@@ -847,8 +883,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB10:
val &= RB10_MASK;
*reg = (*reg & ~RB10_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg);
#endif
@@ -882,8 +918,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
case REG_RB12:
val &= RB12_MASK;
*reg = (*reg & ~RB12_MASK) | val;
val &= mask;
*reg = (*reg & ~mask) | val;
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg);
#endif
@@ -906,6 +942,13 @@ neat_write(uint16_t port, uint8_t val, void *priv)
break;
}
if (mem_size < 1024)
/* No RAM left for EMS at all. */
dev->ems_size = 0;
else if (mem_size < (dev->ems_size + 1024))
/* Limit EMS size to the entirety of the remaining extended memory. */
dev->ems_size = mem_size - 1024;
if (dev->regs[REG_RB7] & RB7_EMSEN) {
remap_update(dev, dev->regs[REG_RB7]);
@@ -976,6 +1019,8 @@ neat_init(UNUSED(const device_t *info))
/* Create an instance. */
dev = (neat_t *) calloc(1, sizeof(neat_t));
dev->sx = info->local;
if (mem_size > 1024) {
mem_mapping_set_handler(&ram_high_mapping, neat_read_ram, neat_read_ramw, NULL,
neat_write_ram, neat_write_ramw, NULL);
@@ -1002,7 +1047,7 @@ neat_init(UNUSED(const device_t *info))
neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_SHADOW);
else {
/* This is needed to actually trigger an update. */
dev->mem_flags[i + 8] = MEM_FLAG_ROMCS;
dev->mem_flags[i + 40] = MEM_FLAG_ROMCS;
neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_SHADOW);
}
}
@@ -1045,7 +1090,10 @@ neat_init(UNUSED(const device_t *info))
/* Initialize some of the registers to specific defaults. */
for (uint8_t i = REG_RA0; i <= REG_RB12; i++) {
dev->indx = i;
neat_write(0x0023, defaults[i & REG_MASK], dev);
uint8_t def = defaults[dev->sx][i & REG_MASK];
if ((i == REG_RA2) && (fpu_type == FPU_387))
def |= RA2_387SX;
neat_write(0x0023, def, dev);
}
/*
@@ -1190,7 +1238,7 @@ neat_init(UNUSED(const device_t *info))
}
const device_t neat_device = {
.name = "C&T CS8121 (NEAT)",
.name = "C&T CS8221 (NEAT)",
.internal_name = "neat",
.flags = 0,
.local = 0,
@@ -1202,3 +1250,17 @@ const device_t neat_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t neat_sx_device = {
.name = "C&T CS8281 (NEATsx)",
.internal_name = "neat_sx",
.flags = 0,
.local = 1,
.init = neat_init,
.close = neat_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -59,8 +59,10 @@
listings on forums, as VIA's datasheets are not very helpful regarding those. */
#define VIA_PIPC_586A 0x05862500
#define VIA_PIPC_586B 0x05864700
#define VIA_PIPC_586 0x0586
#define VIA_PIPC_596A 0x05960900
#define VIA_PIPC_596B 0x05962300
#define VIA_PIPC_596 0x0596
#define VIA_PIPC_686A 0x06861400
#define VIA_PIPC_686B 0x06864000
#define VIA_PIPC_8231 0x82311000
@@ -413,7 +415,9 @@ pipc_reset_hard(void *priv)
dev->power_regs[0x34] = 0x68;
dev->power_regs[0x40] = 0x20;
dev->power_regs[0x42] = 0x50;
dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_586) ? 0x00 : 0x50;
acpi_set_irq_line(dev->acpi, 0x00);
dev->power_regs[0x48] = 0x01;
if (dev->local == VIA_PIPC_686B) {
@@ -1593,6 +1597,9 @@ pipc_reset(void *priv)
pipc_write(pm_func, 0x48, 0x01, priv);
pipc_write(pm_func, 0x49, 0x00, priv);
dev->power_regs[0x42] = ((dev->local >> 16) == VIA_PIPC_586) ? 0x00 : 0x50;
acpi_set_irq_line(dev->acpi, 0x00);
pipc_write(1, 0x04, 0x80, priv);
pipc_write(1, 0x09, 0x85, priv);
pipc_write(1, 0x10, 0xf1, priv);
@@ -1694,6 +1701,8 @@ pipc_init(const device_t *info)
acpi_set_nvr(dev->acpi, dev->nvr);
acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f);
acpi_set_irq_mode(dev->acpi, 0);
}
return dev;

View File

@@ -275,8 +275,8 @@ vt82c49x_write(uint16_t addr, uint8_t val, void *priv)
case 0x71:
if (dev->has_ide) {
ide_pri_disable();
ide_set_base(0, (val & 0x40) ? 0x170 : 0x1f0);
ide_set_side(0, (val & 0x40) ? 0x376 : 0x3f6);
ide_set_base(0, (val & 0x40) ? HDC_SECONDARY_BASE : HDC_PRIMARY_BASE);
ide_set_side(0, (val & 0x40) ? HDC_SECONDARY_SIDE : HDC_PRIMARY_SIDE);
if (val & 0x01)
ide_pri_enable();
vt82c49x_log("VT82C496 IDE now %sabled as %sary\n", (val & 0x01) ? "en" : "dis",

View File

@@ -499,14 +499,14 @@ static int opcode_modrm[256] = {
int opcode_0f_modrm[256] = {
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/

View File

@@ -1643,14 +1643,14 @@ static int opcode_modrm[256] = {
int opcode_0f_modrm[256] = {
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/

View File

@@ -359,14 +359,14 @@ static uint8_t opcode_modrm[256] = {
static uint8_t opcode_0f_modrm[256] = {
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, /*30*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, /*50*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/

View File

@@ -533,7 +533,7 @@ host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data)
codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/
codegen_addword(block, imm_data);
} else if (offset < (1ULL << 32)) {
codegen_alloc_bytes(block, 8);
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0x66, 0xc7, 0x85); /*MOV offset[RBP], imm_data*/
codegen_addlong(block, offset);
codegen_addword(block, imm_data);

View File

@@ -77,6 +77,12 @@
#include <86box/snd_opl.h>
#include <86box/version.h>
#ifndef USE_SDL_UI
/* Deliberate to not make the 86box.h header kitchen-sink. */
#include <86box/qt-glsl.h>
extern char gl3_shader_file[MAX_USER_SHADERS][512];
#endif
static int cx;
static int cy;
static int cw;
@@ -125,6 +131,8 @@ load_general(void)
video_filter_method = ini_section_get_int(cat, "video_filter_method", 1);
inhibit_multimedia_keys = ini_section_get_int(cat, "inhibit_multimedia_keys", 0);
force_43 = !!ini_section_get_int(cat, "force_43", 0);
scale = ini_section_get_int(cat, "scale", 1);
if (scale > 9)
@@ -196,7 +204,6 @@ load_general(void)
video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1);
video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0);
strncpy(video_shader, ini_section_get_string(cat, "video_gl_shader", ""), sizeof(video_shader) - 1);
window_remember = ini_section_get_int(cat, "window_remember", 0);
if (window_remember) {
@@ -1714,6 +1721,51 @@ load_other_peripherals(void)
ini_section_delete_var(cat, temp);
}
#ifndef USE_SDL_UI
/* Load OpenGL 3.0 renderer options. */
static void
load_gl3_shaders(void)
{
ini_section_t cat = ini_find_section(config, "GL3 Shaders");
char *p;
char temp[512];
int i = 0, shaders = 0;
memset(temp, 0, sizeof(temp));
memset(gl3_shader_file, 0, sizeof(gl3_shader_file));
shaders = ini_section_get_int(cat, "shaders", 0);
if (shaders > MAX_USER_SHADERS)
shaders = MAX_USER_SHADERS;
if (shaders == 0) {
ini_section_t general = ini_find_section(config, "General");
if (general) {
p = ini_section_get_string(general, "video_gl_shader", NULL);
if (p) {
if (strlen(p) > 511)
fatal("Configuration: Length of video_gl_shadr is more than 511\n");
else
strncpy(gl3_shader_file[0], p, 511);
ini_delete_var(config, general, "video_gl_shader");
return;
}
}
}
for (i = 0; i < shaders; i++) {
temp[0] = 0;
snprintf(temp, 512, "shader%d", i);
p = ini_section_get_string(cat, temp, "");
if (p[0]) {
strncpy(gl3_shader_file[i], p, 512);
} else {
gl3_shader_file[i][0] = 0;
break;
}
}
}
#endif
/* Load the specified or a default configuration file. */
void
config_load(void)
@@ -1810,6 +1862,9 @@ config_load(void)
load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
load_other_removable_devices(); /* Other removable devices */
load_other_peripherals(); /* Other peripherals */
#ifndef USE_SDL_UI
load_gl3_shaders(); /* GL3 Shaders */
#endif
/* Migrate renamed device configurations. */
c = ini_find_section(config, "MDA");
@@ -1847,6 +1902,10 @@ save_general(void)
const char *va_name;
ini_section_set_int(cat, "inhibit_multimedia_keys", inhibit_multimedia_keys);
if (inhibit_multimedia_keys == 0)
ini_section_delete_var(cat, "inhibit_multimedia_keys");
ini_section_set_int(cat, "sound_muted", sound_muted);
if (sound_muted == 0)
ini_section_delete_var(cat, "sound_muted");
@@ -2002,10 +2061,6 @@ save_general(void)
ini_section_set_int(cat, "video_gl_vsync", video_vsync);
else
ini_section_delete_var(cat, "video_gl_vsync");
if (strlen(video_shader) > 0)
ini_section_set_string(cat, "video_gl_shader", video_shader);
else
ini_section_delete_var(cat, "video_gl_shader");
if (do_auto_pause)
ini_section_set_int(cat, "do_auto_pause", do_auto_pause);
@@ -2632,6 +2687,40 @@ save_other_peripherals(void)
ini_delete_section_if_empty(config, cat);
}
#ifndef USE_SDL_UI
/* Save "GL3 Shaders" section. */
static void
save_gl3_shaders(void)
{
ini_section_t cat = ini_find_or_create_section(config, "GL3 Shaders");
char temp[512];
int shaders = 0, i = 0;
for (i = 0; i < MAX_USER_SHADERS; i++) {
if (gl3_shader_file[i][0] == 0) {
temp[0] = 0;
snprintf(temp, 512, "shader%d", i);
ini_section_delete_var(cat, temp);
break;
}
shaders++;
}
ini_section_set_int(cat, "shaders", shaders);
if (shaders == 0) {
ini_section_delete_var(cat, "shaders");
} else {
for (i = 0; i < shaders; i++) {
temp[0] = 0;
snprintf(temp, 512, "shader%d", i);
ini_section_set_string(cat, temp, gl3_shader_file[i]);
}
}
ini_delete_section_if_empty(config, cat);
}
#endif
/* Save "Hard Disks" section. */
static void
save_hard_disks(void)
@@ -2922,6 +3011,19 @@ save_other_removable_devices(void)
else
ini_section_set_string(cat, temp, zip_drives[c].image_path);
}
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
sprintf(temp, "zip_%02i_image_history_%02i", c + 1, i + 1);
if ((zip_drives[c].image_history[i] == 0) || strlen(zip_drives[c].image_history[i]) == 0)
ini_section_delete_var(cat, temp);
else {
path_normalize(zip_drives[c].image_history[i]);
if (!strnicmp(zip_drives[c].image_history[i], usr_path, strlen(usr_path)))
ini_section_set_string(cat, temp, &zip_drives[c].image_history[i][strlen(usr_path)]);
else
ini_section_set_string(cat, temp, zip_drives[c].image_history[i]);
}
}
}
for (c = 0; c < MO_NUM; c++) {
@@ -2965,6 +3067,19 @@ save_other_removable_devices(void)
else
ini_section_set_string(cat, temp, mo_drives[c].image_path);
}
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
sprintf(temp, "mo_%02i_image_history_%02i", c + 1, i + 1);
if ((mo_drives[c].image_history[i] == 0) || strlen(mo_drives[c].image_history[i]) == 0)
ini_section_delete_var(cat, temp);
else {
path_normalize(mo_drives[c].image_history[i]);
if (!strnicmp(mo_drives[c].image_history[i], usr_path, strlen(usr_path)))
ini_section_set_string(cat, temp, &mo_drives[c].image_history[i][strlen(usr_path)]);
else
ini_section_set_string(cat, temp, mo_drives[c].image_history[i]);
}
}
}
ini_delete_section_if_empty(config, cat);
@@ -2987,6 +3102,9 @@ config_save(void)
save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
save_other_removable_devices(); /* Other removable devices */
save_other_peripherals(); /* Other peripherals */
#ifndef USE_SDL_UI
save_gl3_shaders(); /* GL3 Shaders */
#endif
ini_write(config, cfg_path);
}

View File

@@ -264,18 +264,20 @@ exec386_2386(int32_t cycs)
ol = opcode_length[fetchdat & 0xff];
if ((ol == 3) && opcode_has_modrm[fetchdat & 0xff] && (((fetchdat >> 14) & 0x03) == 0x03))
ol = 2;
if (cpu_16bitbus) {
CHECK_READ_CS(MIN(ol, 2));
} else {
CHECK_READ_CS(MIN(ol, 4));
}
if (is386)
ins_fetch_fault = cpu_386_check_instruction_fault();
/* Breakpoint fault has priority over other faults. */
if (ins_fetch_fault) {
if ((cpu_state.abrt == 0) & ins_fetch_fault) {
x86gen();
ins_fetch_fault = 0;
cpu_state.abrt = 1;
/* No instructions executed at this point. */
goto block_ended;
} else if (cpu_16bitbus) {
CHECK_READ_CS(MIN(ol, 2));
} else {
CHECK_READ_CS(MIN(ol, 4));
}
if (!cpu_state.abrt) {
@@ -288,7 +290,6 @@ exec386_2386(int32_t cycs)
trap |= !!(cpu_state.flags & T_FLAG);
cpu_state.pc++;
cpu_state.eflags &= ~(RF_FLAG);
if (opcode == 0xf0)
in_lock = 1;
x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
@@ -316,6 +317,7 @@ exec386_2386(int32_t cycs)
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
block_ended:
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
@@ -338,6 +340,9 @@ exec386_2386(int32_t cycs)
#endif
}
}
if (is386 && !x86_was_reset && ins_fetch_fault)
x86gen();
} else if (new_ne) {
flags_rebuild();
new_ne = 0;

View File

@@ -107,6 +107,12 @@ uint32_t backupregs[16];
x86seg _oldds;
uint8_t rep_op = 0x00;
uint8_t is_smint = 0;
uint16_t io_port = 0x0000;
uint32_t io_val = 0x00000000;
int opcode_has_modrm[256] = {
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
@@ -1215,7 +1221,7 @@ smram_restore_state_amd_k(uint32_t *saved_state)
}
static void
smram_save_state_cyrix(uint32_t *saved_state, UNUSED(int in_hlt))
smram_save_state_cyrix(uint32_t *saved_state, int in_hlt)
{
saved_state[0] = dr[7];
saved_state[1] = cpu_state.flags | (cpu_state.eflags << 16);
@@ -1224,6 +1230,35 @@ smram_save_state_cyrix(uint32_t *saved_state, UNUSED(int in_hlt))
saved_state[4] = cpu_state.pc;
saved_state[5] = CS | (CPL << 21);
saved_state[6] = 0x00000000;
saved_state[7] = 0x00010000;
if (((opcode >= 0x6e) && (opcode <= 0x6f)) || ((opcode >= 0xe6) && (opcode <= 0xe7)) ||
((opcode >= 0xee) && (opcode <= 0xef))) {
saved_state[6] |= 0x00000002;
saved_state[7] = (opcode & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000;
} else if (((opcode == 0xf2) || (opcode == 0xf3)) && (rep_op >= 0x6e) && (rep_op <= 0x6f)) {
saved_state[6] |= 0x00000006;
saved_state[7] = (rep_op & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000;
} else if (((opcode == 0xf2) || (opcode == 0xf3)) && (rep_op >= 0x6e) && (rep_op <= 0x6f)) {
saved_state[6] |= 0x00000004;
saved_state[7] = (rep_op & 0x01) ? (cpu_state.op32 ? 0x000f0000 : 0x00030000) : 0x00010000;
}
if (is_smint) {
saved_state[6] |= 0x00000008;
is_smint = 0;
}
if (in_hlt)
saved_state[6] |= 0x00000010;
saved_state[7] |= io_port;
saved_state[8] = io_val;
if (saved_state[6] & 0x00000002)
saved_state[9] = ESI;
else
saved_state[9] = EDI;
}
static void
@@ -1234,6 +1269,13 @@ smram_restore_state_cyrix(uint32_t *saved_state)
cpu_state.eflags = saved_state[1] >> 16;
cr0 = saved_state[2];
cpu_state.pc = saved_state[4];
/* Restore CPL. */
cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~0x9f) | (((saved_state[5] >> 21) & 0x03) << 5);
if (saved_state[6] & 0x00000002)
ESI = saved_state[9];
else
EDI = saved_state[9];
}
void
@@ -1368,6 +1410,9 @@ enter_smm(int in_hlt)
writememl(0, smram_state - 0x14, saved_state[4]);
writememl(0, smram_state - 0x18, saved_state[5]);
writememl(0, smram_state - 0x24, saved_state[6]);
writememl(0, smram_state - 0x28, saved_state[7]);
writememl(0, smram_state - 0x2c, saved_state[8]);
writememl(0, smram_state - 0x30, saved_state[9]);
} else {
for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) {
smram_state -= 4;
@@ -1404,26 +1449,44 @@ enter_smm(int in_hlt)
void
enter_smm_check(int in_hlt)
{
if ((in_smm == 0) && smi_line) {
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while not in SMM\n");
#endif
enter_smm(in_hlt);
} else if ((in_smm == 1) && smi_line) {
/* Mark this so that we don't latch more than one SMI. */
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while in unlatched SMM\n");
#endif
smi_latched = 1;
} else if ((in_smm == 2) && smi_line) {
/* Mark this so that we don't latch more than one SMI. */
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while in latched SMM\n");
#endif
}
uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) && (cyrix.arr[3].size > 0);
if (smi_line) {
if (!is_cxsmm || ccr1_check) switch (in_smm) {
default:
#ifdef ENABLE_386_COMMON_LOG
fatal("SMI while in_smm = %i\n", in_smm);
break;
#endif
case 0:
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while not in SMM\n");
#endif
enter_smm(in_hlt);
break;
case 1:
/* Mark this so that we don't latch more than one SMI. */
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while in unlatched SMM\n");
#endif
smi_latched = 1;
break;
case 2:
#ifdef ENABLE_386_COMMON_LOG
x386_common_log("SMI while in latched SMM\n");
#endif
break;
}
#ifdef ENABLE_386_COMMON_LOG
else {
x386_common_log("SMI while in Cyrix disabled mode\n");
x386_common_log("lol\n");
}
#endif
if (smi_line)
smi_line = 0;
}
}
void
@@ -1452,6 +1515,9 @@ leave_smm(void)
else
cyrix_load_seg_descriptor_2386(smram_state - 0x20, &cpu_state.seg_cs);
saved_state[6] = readmeml(0, smram_state - 0x24);
saved_state[7] = readmeml(0, smram_state - 0x28);
saved_state[8] = readmeml(0, smram_state - 0x2c);
saved_state[9] = readmeml(0, smram_state - 0x30);
} else {
for (uint8_t n = 0; n < SMM_SAVE_STATE_MAP_SIZE; n++) {
smram_state -= 4;
@@ -2138,6 +2204,12 @@ cpu_fast_off_reset(void)
void
smi_raise(void)
{
uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) && (cyrix.arr[3].size > 0);
if (is_cxsmm && !ccr1_check)
return;
if (is486 && (cpu_fast_off_flags & 0x80000000))
cpu_fast_off_advance();

View File

@@ -276,11 +276,7 @@ exec386_dynarec_int(void)
cpu_block_end = 0;
x86_was_reset = 0;
# ifdef USE_DEBUG_REGS_486
if (trap & 2) {
# else
if (trap == 2) {
# endif
/* Handle the T bit in the new TSS first. */
CPU_BLOCK_END();
goto block_ended;
@@ -297,13 +293,6 @@ exec386_dynarec_int(void)
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
# ifdef USE_DEBUG_REGS_486
if (UNLIKELY(cpu_386_check_instruction_fault())) {
x86gen();
goto block_ended;
}
# endif
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
# ifdef ENABLE_386_DYNAREC_LOG
if (in_smm)
@@ -370,13 +359,7 @@ exec386_dynarec_int(void)
block_ended:
if (!cpu_state.abrt && !new_ne && trap) {
# ifdef USE_DEBUG_REGS_486
//pclog("Debug trap 0x%X\n", trap);
if (trap & 2) dr[6] |= 0x8000;
if (trap & 1) dr[6] |= 0x4000;
# else
dr[6] |= (trap == 2) ? 0x8000 : 0x4000;
# endif
trap = 0;
# ifndef USE_NEW_DYNAREC
@@ -902,6 +885,9 @@ exec386(int32_t cycs)
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
#ifdef USE_DEBUG_REGS_486
int ins_fetch_fault = 0;
#endif
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
@@ -919,8 +905,14 @@ exec386(int32_t cycs)
cpu_state.ssegs = 0;
#ifdef USE_DEBUG_REGS_486
if (UNLIKELY(cpu_386_check_instruction_fault())) {
if (is386)
ins_fetch_fault = cpu_386_check_instruction_fault();
/* Breakpoint fault has priority over other faults. */
if ((cpu_state.abrt == 0) & ins_fetch_fault) {
x86gen();
ins_fetch_fault = 0;
/* No instructions executed at this point. */
goto block_ended;
}
#endif
@@ -972,11 +964,13 @@ exec386(int32_t cycs)
block_ended:
#endif
if (cpu_state.abrt) {
uint8_t oop = opcode;
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt) {
pclog("Double fault - %02X\n", oop);
cpu_state.abrt = 0;
#ifndef USE_NEW_DYNAREC
CS = oldcs;
@@ -993,6 +987,11 @@ block_ended:
#endif
}
}
#ifdef USE_DEBUG_REGS_486
if (is386 && !x86_was_reset && ins_fetch_fault)
x86gen();
#endif
} else if (new_ne) {
flags_rebuild();
@@ -1005,20 +1004,14 @@ block_ended:
} else if (trap) {
flags_rebuild();
#ifdef USE_DEBUG_REGS_486
if (trap & 1)
dr[6] |= 0x4000;
if (trap & 2)
dr[6] |= 0x8000;
if (trap & 2) dr[6] |= 0x8000;
if (trap & 1) dr[6] |= 0x4000;
#endif
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
#ifndef USE_DEBUG_REGS_486
dr[6] |= 0x4000;
#endif
x86_int(1);
}

View File

@@ -1,290 +0,0 @@
/*
* 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.
*
* 8080 CPU emulation.
*
* Authors: Cacodemon345
*
* Copyright 2022 Cacodemon345
*/
#include <stdint.h>
#include <stdlib.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/i8080.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
static int completed = 1;
static int in_rep = 0;
static int repeating = 0;
static int rep_c_flag = 0;
static int oldc;
static int cycdiff;
#ifdef UNUSED_8080_VARS
static int prefetching = 1;
static int refresh = 0;
static int clear_lock = 0;
static uint32_t cpu_src = 0;
static uint32_t cpu_dest = 0;
static uint32_t cpu_data = 0;
#endif
static void
clock_start(void)
{
cycdiff = cycles;
}
static void
clock_end(void)
{
int diff = cycdiff - cycles;
/* On 808x systems, clock speed is usually crystal frequency divided by an integer. */
tsc += (uint64_t) diff * (xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process();
}
static void
i8080_wait(int c, int bus)
{
cycles -= c;
if (bus < 2) {
clock_end();
clock_start();
}
}
#ifdef UNUSED_8080_FUNCS
static uint8_t
readmemb(uint32_t a)
{
uint8_t ret;
i8080_wait(4, 1);
ret = read_mem_b(a);
return ret;
}
static uint8_t
ins_fetch(i8080 *cpu)
{
uint8_t ret = cpu->readmembyte(cpu->pmembase + cpu->pc);
cpu->pc++;
return ret;
}
#endif
void
transfer_from_808x(i8080 *cpu)
{
cpu->hl = BX;
cpu->bc = CX;
cpu->de = DX;
cpu->a = AL;
cpu->flags = cpu_state.flags & 0xFF;
cpu->sp = BP;
cpu->pc = cpu_state.pc;
cpu->oldpc = cpu_state.oldpc;
cpu->pmembase = cs;
cpu->dmembase = ds;
}
void
transfer_to_808x(i8080 *cpu)
{
BX = cpu->hl;
CX = cpu->bc;
DX = cpu->de;
AL = cpu->a;
cpu_state.flags &= 0xFF00;
cpu_state.flags |= cpu->flags & 0xFF;
BP = cpu->sp;
cpu_state.pc = cpu->pc;
}
uint8_t
getreg_i8080(i8080 *cpu, uint8_t reg)
{
uint8_t ret = 0xFF;
switch (reg) {
case 0x0:
ret = cpu->b;
break;
case 0x1:
ret = cpu->c;
break;
case 0x2:
ret = cpu->d;
break;
case 0x3:
ret = cpu->e;
break;
case 0x4:
ret = cpu->h;
break;
case 0x5:
ret = cpu->l;
break;
case 0x6:
ret = cpu->readmembyte(cpu->dmembase + cpu->sp);
break;
case 0x7:
ret = cpu->a;
break;
}
return ret;
}
uint8_t
getreg_i8080_emu(i8080 *cpu, uint8_t reg)
{
uint8_t ret = 0xFF;
switch (reg) {
case 0x0:
ret = CH;
break;
case 0x1:
ret = CL;
break;
case 0x2:
ret = DH;
break;
case 0x3:
ret = DL;
break;
case 0x4:
ret = BH;
break;
case 0x5:
ret = BL;
break;
case 0x6:
ret = cpu->readmembyte(cpu->dmembase + BP);
break;
case 0x7:
ret = AL;
break;
}
return ret;
}
void
setreg_i8080_emu(i8080 *cpu, uint8_t reg, uint8_t val)
{
switch (reg) {
case 0x0:
CH = val;
break;
case 0x1:
CL = val;
break;
case 0x2:
DH = val;
break;
case 0x3:
DL = val;
break;
case 0x4:
BH = val;
break;
case 0x5:
BL = val;
break;
case 0x6:
cpu->writemembyte(cpu->dmembase + BP, val);
break;
case 0x7:
AL = val;
break;
}
}
void
setreg_i8080(i8080 *cpu, uint8_t reg, uint8_t val)
{
switch (reg) {
case 0x0:
cpu->b = val;
break;
case 0x1:
cpu->c = val;
break;
case 0x2:
cpu->d = val;
break;
case 0x3:
cpu->e = val;
break;
case 0x4:
cpu->h = val;
break;
case 0x5:
cpu->l = val;
break;
case 0x6:
cpu->writemembyte(cpu->dmembase + cpu->sp, val);
break;
case 0x7:
cpu->a = val;
break;
}
}
void
interpret_exec8080(UNUSED(i8080 *cpu), uint8_t opcode)
{
switch (opcode) {
case 0x00:
{
break;
}
}
}
/* Actually implement i8080 emulation. */
void
exec8080(i8080 *cpu, int cycs)
{
#ifdef UNUSED_8080_VARS
uint8_t temp = 0, temp2;
uint8_t old_af;
uint8_t handled = 0;
uint16_t addr, tempw;
uint16_t new_ip;
int bits;
#endif
cycles += cycs;
while (cycles > 0) {
cpu->startclock();
if (!repeating) {
cpu->oldpc = cpu->pc;
opcode = cpu->fetchinstruction(cpu);
oldc = cpu->flags & C_FLAG_I8080;
i8080_wait(1, 0);
}
completed = 1;
if (completed) {
repeating = 0;
in_rep = 0;
rep_c_flag = 0;
cpu->endclock();
if (cpu->checkinterrupts)
cpu->checkinterrupts();
}
}
}

View File

@@ -18,10 +18,13 @@
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include "i8080.h"
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
@@ -70,6 +73,9 @@ static int in_rep = 0, repeating = 0, rep_c_flag = 0;
static int oldc, clear_lock = 0;
static int refresh = 0, cycdiff;
static i8080 emulated_processor;
static bool cpu_md_write_disable = 1;
/* Various things needed for 8087. */
#define OP_TABLE(name) ops_##name
@@ -195,6 +201,56 @@ prefetch_queue_get_size(void)
{
return pfq_size;
}
static void set_if(int cond);
void
sync_from_i8080(void)
{
AL = emulated_processor.a;
BH = emulated_processor.h;
BL = emulated_processor.l;
CH = emulated_processor.b;
CL = emulated_processor.c;
DH = emulated_processor.d;
DL = emulated_processor.e;
BP = emulated_processor.sp;
cpu_state.pc = emulated_processor.pc;
cpu_state.flags &= 0xFF00;
cpu_state.flags |= emulated_processor.sf << 7;
cpu_state.flags |= emulated_processor.zf << 6;
cpu_state.flags |= emulated_processor.hf << 4;
cpu_state.flags |= emulated_processor.pf << 2;
cpu_state.flags |= 1 << 1;
cpu_state.flags |= emulated_processor.cf << 0;
set_if(emulated_processor.iff);
}
void
sync_to_i8080(void)
{
if (!is_nec)
return;
emulated_processor.a = AL;
emulated_processor.h = BH;
emulated_processor.l = BL;
emulated_processor.b = CH;
emulated_processor.c = CL;
emulated_processor.d = DH;
emulated_processor.e = DL;
emulated_processor.sp = BP;
emulated_processor.pc = cpu_state.pc;
emulated_processor.iff = !!(cpu_state.flags & I_FLAG);
emulated_processor.sf = (cpu_state.flags >> 7) & 1;
emulated_processor.zf = (cpu_state.flags >> 6) & 1;
emulated_processor.hf = (cpu_state.flags >> 4) & 1;
emulated_processor.pf = (cpu_state.flags >> 2) & 1;
emulated_processor.cf = (cpu_state.flags >> 0) & 1;
emulated_processor.interrupt_delay = noint;
}
uint16_t
get_last_addr(void)
@@ -582,6 +638,33 @@ load_seg(uint16_t seg, x86seg *s)
s->seg = seg & 0xffff;
}
uint8_t fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr)
{
return readmemb(cs + addr);
}
uint8_t fetch_i8080_data(UNUSED(void* priv), uint16_t addr)
{
return readmemb(ds + addr);
}
void put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val)
{
writememb(ds, addr, val);
}
static uint8_t i8080_port_in(UNUSED(void* priv), uint8_t port)
{
cpu_io(8, 0, port);
return AL;
}
static void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val)
{
AL = val;
cpu_io(8, 1, port);
}
void
reset_808x(int hard)
{
@@ -619,6 +702,14 @@ reset_808x(int hard)
use_custom_nmi_vector = 0x00;
custom_nmi_vector = 0x00000000;
cpu_md_write_disable = 1;
i8080_init(&emulated_processor);
emulated_processor.write_byte = put_i8080_data;
emulated_processor.read_byte = fetch_i8080_data;
emulated_processor.read_byte_seg = fetch_i8080_opcode;
emulated_processor.port_in = i8080_port_in;
emulated_processor.port_out = i8080_port_out;
}
static void
@@ -994,6 +1085,11 @@ interrupt(uint16_t addr)
uint16_t new_cs, new_ip;
uint16_t tempf;
if (!(cpu_state.flags & MD_FLAG) && is_nec) {
sync_from_i8080();
x808x_log("CALLN/INT#/NMI#\n");
}
addr <<= 2;
cpu_state.eaaddr = addr;
old_cs = CS;
@@ -1010,6 +1106,8 @@ interrupt(uint16_t addr)
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
push(&tempf);
cpu_state.flags &= ~(I_FLAG | T_FLAG);
if (is_nec)
cpu_state.flags |= MD_FLAG;
access(40, 16);
push(&old_cs);
old_ip = cpu_state.pc;
@@ -1020,6 +1118,65 @@ interrupt(uint16_t addr)
push(&old_ip);
}
/* Ditto, but for breaking into emulation mode. */
static void
interrupt_brkem(uint16_t addr)
{
uint16_t old_cs, old_ip;
uint16_t new_cs, new_ip;
uint16_t tempf;
addr <<= 2;
cpu_state.eaaddr = addr;
old_cs = CS;
access(5, 16);
new_ip = readmemw(0, cpu_state.eaaddr);
wait(1, 0);
cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff;
access(6, 16);
new_cs = readmemw(0, cpu_state.eaaddr);
prefetching = 0;
pfq_clear();
ovr_seg = NULL;
access(39, 16);
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
push(&tempf);
cpu_state.flags &= ~(MD_FLAG);
cpu_md_write_disable = 0;
access(40, 16);
push(&old_cs);
old_ip = cpu_state.pc;
load_cs(new_cs);
access(68, 16);
set_ip(new_ip);
access(41, 16);
push(&old_ip);
sync_to_i8080();
x808x_log("BRKEM mode\n");
}
void
retem_i8080(void)
{
sync_from_i8080();
prefetching = 0;
pfq_clear();
set_ip(pop());
load_cs(pop());
cpu_state.flags = pop();
emulated_processor.iff = !!(cpu_state.flags & I_FLAG);
cpu_md_write_disable = 1;
noint = 1;
nmi_enable = 1;
x808x_log("RETEM mode\n");
}
void
interrupt_808x(uint16_t addr)
{
@@ -1033,6 +1190,11 @@ custom_nmi(void)
uint16_t new_cs, new_ip;
uint16_t tempf;
if (!(cpu_state.flags & MD_FLAG) && is_nec) {
sync_from_i8080();
pclog("NMI# (CUTSOM)\n");
}
cpu_state.eaaddr = 0x0002;
old_cs = CS;
access(5, 16);
@@ -1050,6 +1212,8 @@ custom_nmi(void)
tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7);
push(&tempf);
cpu_state.flags &= ~(I_FLAG | T_FLAG);
if (is_nec)
cpu_state.flags |= MD_FLAG;
access(40, 16);
push(&old_cs);
old_ip = cpu_state.pc;
@@ -1771,6 +1935,15 @@ execx86(int cycs)
while (cycles > 0) {
clock_start();
if (is_nec && !(cpu_state.flags & MD_FLAG)) {
i8080_step(&emulated_processor);
set_if(emulated_processor.iff);
cycles -= emulated_processor.cyc;
emulated_processor.cyc = 0;
completed = 1;
goto exec_completed;
}
if (!repeating) {
cpu_state.oldpc = cpu_state.pc;
opcode = pfq_fetchb();
@@ -2344,8 +2517,8 @@ execx86(int cycs)
break;
case 0xFF: /* BRKEM */
/* Unimplemented for now. */
fatal("808x: Unsupported 8080 emulation mode attempted to enter into!");
interrupt_brkem(pfq_fetchb());
handled = 1;
break;
default:
@@ -2857,11 +3030,12 @@ execx86(int cycs)
break;
case 0x9D: /*POPF*/
access(25, 16);
if (is_nec)
if (is_nec && cpu_md_write_disable)
cpu_state.flags = pop() | 0x8002;
else
cpu_state.flags = pop() | 0x0002;
wait(1, 0);
sync_to_i8080();
break;
case 0x9E: /*SAHF*/
wait(1, 0);
@@ -3127,13 +3301,15 @@ execx86(int cycs)
access(62, 8);
set_ip(new_ip);
access(45, 8);
if (is_nec)
if (is_nec && cpu_md_write_disable)
cpu_state.flags = pop() | 0x8002;
else
cpu_state.flags = pop() | 0x0002;
wait(5, 0);
noint = 1;
nmi_enable = 1;
if (is_nec && !(cpu_state.flags & MD_FLAG))
sync_to_i8080();
break;
case 0xD0:
@@ -3659,7 +3835,7 @@ execx86(int cycs)
break;
}
}
exec_completed:
if (completed) {
repeating = 0;
ovr_seg = NULL;

View File

@@ -29,7 +29,7 @@ add_library(cpu OBJECT
x86seg_2386.c
x87.c
x87_timings.c
8080.c
i8080.c
)
if(AMD_K5)

View File

@@ -40,6 +40,7 @@
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/smram.h>
#include <86box/timer.h>
#include <86box/gdbstub.h>
#include <86box/plat_fallthrough.h>
@@ -50,13 +51,6 @@
#endif /* USE_DYNAREC */
#include "x87_timings.h"
#define CCR1_USE_SMI (1 << 1)
#define CCR1_SMAC (1 << 2)
#define CCR1_SM3 (1 << 7)
#define CCR3_SMI_LOCK (1 << 0)
#define CCR3_NMI_EN (1 << 1)
enum {
CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */
CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */
@@ -209,6 +203,7 @@ int is286;
int is386;
int is6117;
int is486 = 1;
int is586 = 0;
int cpu_isintel;
int cpu_iscyrix;
int hascache;
@@ -289,6 +284,13 @@ uint8_t ccr5;
uint8_t ccr6;
uint8_t ccr7;
uint8_t reg_30 = 0x00;
uint8_t arr[24] = { 0 };
uint8_t rcr[8] = { 0 };
/* Table for FXTRACT. */
double exp_pow_table[0x800];
static int cyrix_addr;
static void cpu_write(uint16_t addr, uint8_t val, void *priv);
@@ -384,6 +386,14 @@ cpu_is_eligible(const cpu_family_t *cpu_family, int cpu, int machine)
if (cpu_override)
return 1;
/* Cyrix 6x86MX on the NuPRO 592. */
if (((cpu_s->cyrix_id & 0xff00) == 0x0400) && (strstr(machine_s->internal_name, "nupro") != NULL))
return 0;
/* Cyrix 6x86MX or MII on the P5MMS98. */
if ((cpu_s->cpu_type == CPU_Cx6x86MX) && (strstr(machine_s->internal_name, "p5mms98") != NULL))
return 0;
/* Check CPU blocklist. */
if (machine_s->cpu.block) {
i = 0;
@@ -553,6 +563,8 @@ cpu_set(void)
cpu_16bitbus = (cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) || (cpu_s->cpu_type == CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC) || (cpu_s->cpu_type == CPU_IBM486SLC);
cpu_64bitbus = (cpu_s->cpu_type >= CPU_WINCHIP);
is586 = cpu_64bitbus || (cpu_s->cpu_type == CPU_P24T);
if (cpu_s->multi)
cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
else
@@ -2617,6 +2629,23 @@ cpu_ven_reset(void)
msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL;
break;
case CPU_Cx6x86MX:
ccr0 = 0x00;
ccr1 = 0x00;
ccr2 = 0x00;
ccr3 = 0x00;
ccr4 = 0x80;
ccr5 = 0x00;
ccr6 = 0x00;
memset(arr, 0x00, 24);
memset(rcr, 0x00, 3);
cyrix.arr[3].base = 0x00;
cyrix.arr[3].size = 0; /* Disabled */
cyrix.smhr &= ~SMHR_VALID;
CPUID = cpu_s->cpuid_model;
reg_30 = 0xff;
break;
case CPU_PENTIUMPRO:
case CPU_PENTIUM2:
case CPU_PENTIUM2D:
@@ -3949,12 +3978,15 @@ pentium_invalid_wrmsr:
/* Test Data */
case 0x03:
msr.tr3 = EAX;
break;
/* Test Address */
case 0x04:
msr.tr4 = EAX;
break;
/* Test Command/Status */
case 0x05:
msr.tr5 = EAX & 0x008f0f3b;
break;
/* Time Stamp Counter */
case 0x10:
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
@@ -4224,124 +4256,179 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
picintc(1 << 13);
else
nmi = 0;
return;
} else if (addr >= 0xf1)
return; /* FPU stuff */
if (!(addr & 1))
} else if ((addr < 0xf1) && !(addr & 1))
cyrix_addr = val;
else
switch (cyrix_addr) {
case 0xc0: /* CCR0 */
ccr0 = val;
break;
case 0xc1: /* CCR1 */
if ((ccr3 & CCR3_SMI_LOCK) && !in_smm)
val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3));
ccr1 = val;
break;
case 0xc2: /* CCR2 */
ccr2 = val;
break;
case 0xc3: /* CCR3 */
if ((ccr3 & CCR3_SMI_LOCK) && !in_smm)
val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK;
ccr3 = val;
break;
case 0xcd:
if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) {
cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24);
cyrix.smhr &= ~SMHR_VALID;
}
break;
case 0xce:
if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) {
cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16);
cyrix.smhr &= ~SMHR_VALID;
}
break;
case 0xcf:
if (!(ccr3 & CCR3_SMI_LOCK) || in_smm) {
cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8);
if ((val & 0xf) == 0xf)
cyrix.arr[3].size = 1ULL << 32; /* 4 GB */
else if (val & 0xf)
cyrix.arr[3].size = 2048 << (val & 0xf);
else
cyrix.arr[3].size = 0; /* Disabled */
cyrix.smhr &= ~SMHR_VALID;
}
break;
else if (addr < 0xf1) switch (cyrix_addr) {
default:
if (cyrix_addr >= 0xc0)
fatal("Writing unimplemented Cyrix register %02X\n", cyrix_addr);
break;
case 0xe8: /* CCR4 */
if ((ccr3 & 0xf0) == 0x10) {
ccr4 = val;
if (cpu_s->cpu_type >= CPU_Cx6x86) {
if (val & 0x80)
CPUID = cpu_s->cpuid_model;
else
CPUID = 0;
}
case 0x30: /* ???? */
reg_30 = val;
break;
case 0xc0: /* CCR0 */
ccr0 = val;
break;
case 0xc1: { /* CCR1 */
uint8_t old = ccr1;
if ((ccr3 & CCR3_SMI_LOCK) && !in_smm)
val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3));
ccr1 = val;
if ((old ^ ccr1) & (CCR1_SMAC)) {
if (ccr1 & CCR1_SMAC)
smram_backup_all();
smram_recalc_all(!(ccr1 & CCR1_SMAC));
}
break;
} case 0xc2: /* CCR2 */
ccr2 = val;
break;
case 0xc3: /* CCR3 */
if ((ccr3 & CCR3_SMI_LOCK) && !in_smm)
val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK;
ccr3 = val;
break;
case 0xc4 ... 0xcc:
if (ccr5 & 0x20)
arr[cyrix_addr - 0xc4] = val;
break;
case 0xcd:
if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) {
arr[cyrix_addr - 0xc4] = val;
cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24);
cyrix.smhr &= ~SMHR_VALID;
}
break;
case 0xce:
if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) {
arr[cyrix_addr - 0xc4] = val;
cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16);
cyrix.smhr &= ~SMHR_VALID;
}
break;
case 0xcf:
if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm)) {
arr[cyrix_addr - 0xc4] = val;
cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8);
if ((val & 0xf) == 0xf)
cyrix.arr[3].size = 1ULL << 32; /* 4 GB */
else if (val & 0xf)
cyrix.arr[3].size = 2048 << (val & 0xf);
else
cyrix.arr[3].size = 0; /* Disabled */
cyrix.smhr &= ~SMHR_VALID;
}
break;
case 0xd0 ... 0xdb:
if (((ccr3 & 0xf0) == 0x10) && (ccr5 & 0x20))
arr[cyrix_addr - 0xc4] = val;
break;
case 0xdc ... 0xe3:
if ((ccr3 & 0xf0) == 0x10)
rcr[cyrix_addr - 0xdc] = val;
break;
case 0xe8: /* CCR4 */
if ((ccr3 & 0xf0) == 0x10) {
ccr4 = val;
if (cpu_s->cpu_type >= CPU_Cx6x86) {
if (val & 0x80)
CPUID = cpu_s->cpuid_model;
else
CPUID = 0;
}
break;
case 0xe9: /* CCR5 */
if ((ccr3 & 0xf0) == 0x10)
ccr5 = val;
break;
case 0xea: /* CCR6 */
if ((ccr3 & 0xf0) == 0x10)
ccr6 = val;
break;
case 0xeb: /* CCR7 */
ccr7 = val & 5;
break;
}
}
break;
case 0xe9: /* CCR5 */
if ((ccr3 & 0xf0) == 0x10)
ccr5 = val;
break;
case 0xea: /* CCR6 */
if ((ccr3 & 0xf0) == 0x10)
ccr6 = val;
break;
case 0xeb: /* CCR7 */
ccr7 = val & 5;
break;
}
}
static uint8_t
cpu_read(uint16_t addr, UNUSED(void *priv))
{
uint8_t ret = 0xff;
if (addr == 0xf007)
return 0x7f;
ret = 0x7f;
else if ((addr < 0xf0) && (addr & 1)) switch (cyrix_addr) {
default:
if (cyrix_addr >= 0xc0)
fatal("Reading unimplemented Cyrix register %02X\n", cyrix_addr);
break;
if (addr >= 0xf0)
return 0xff; /* FPU stuff */
case 0x30: /* ???? */
ret = reg_30;
break;
if (addr & 1) {
switch (cyrix_addr) {
case 0xc0:
return ccr0;
case 0xc1:
return ccr1;
case 0xc2:
return ccr2;
case 0xc3:
return ccr3;
case 0xe8:
return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff;
case 0xe9:
return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff;
case 0xea:
return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff;
case 0xeb:
return ccr7;
case 0xfe:
return cpu_s->cyrix_id & 0xff;
case 0xff:
return cpu_s->cyrix_id >> 8;
case 0xc0:
ret = ccr0;
break;
case 0xc1:
ret = ccr1;
break;
case 0xc2:
ret = ccr2;
break;
case 0xc3:
ret = ccr3;
break;
default:
break;
}
case 0xc4 ... 0xcc:
if (ccr5 & 0x20)
ret = arr[cyrix_addr - 0xc4];
break;
case 0xcd ... 0xcf:
if ((ccr5 & 0x20) || (!(ccr3 & CCR3_SMI_LOCK) || in_smm))
ret = arr[cyrix_addr - 0xc4];
break;
case 0xd0 ... 0xdb:
if (((ccr3 & 0xf0) == 0x10) && (ccr5 & 0x20))
ret = arr[cyrix_addr - 0xc4];
break;
if ((cyrix_addr & 0xf0) == 0xc0)
return 0xff;
case 0xdc ... 0xe3:
if ((ccr3 & 0xf0) == 0x10)
ret = rcr[cyrix_addr - 0xdc];
break;
if (cyrix_addr == 0x20 && (cpu_s->cpu_type == CPU_Cx5x86))
return 0xff;
case 0xe8:
if ((ccr3 & 0xf0) == 0x10)
ret = ccr4;
break;
case 0xe9:
if ((ccr3 & 0xf0) == 0x10)
ret = ccr5;
break;
case 0xea:
if ((ccr3 & 0xf0) == 0x10)
ret = ccr6;
break;
case 0xeb:
ret = ccr7;
break;
case 0xfe:
ret = cpu_s->cyrix_id & 0xff;
break;
case 0xff:
ret = cpu_s->cyrix_id >> 8;
break;
}
return 0xff;
return ret;
}
void

View File

@@ -120,6 +120,13 @@ enum {
#define CPU_ALTERNATE_XTAL 4
#define CPU_FIXED_MULTIPLIER 8
#define CCR1_USE_SMI (1 << 1)
#define CCR1_SMAC (1 << 2)
#define CCR1_SM3 (1 << 7)
#define CCR3_SMI_LOCK (1 << 0)
#define CCR3_NMI_EN (1 << 1)
#if (defined __amd64__ || defined _M_X64)
# define LOOKUP_INV -1LL
#else
@@ -513,6 +520,7 @@ extern int is286;
extern int is386;
extern int is6117;
extern int is486;
extern int is586;
extern int is_am486;
extern int is_am486dxl;
extern int is_pentium;

View File

@@ -6366,6 +6366,74 @@ const cpu_family_t cpu_families[] = {
.name = "MII",
.internal_name = "mii",
.cpus = (const CPU[]) {
{
.name = "IBM 133 (PR166)",
.cpu_type = CPU_Cx6x86MX,
.fpus = fpus_internal,
.rspeed = 133333333,
.multi = 2.0,
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0851,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 12,
.mem_write_cycles = 12,
.cache_read_cycles = 6,
.cache_write_cycles = 6,
.atclk_div = 16
},
{
.name = "166 (PR200)",
.cpu_type = CPU_Cx6x86MX,
.fpus = fpus_internal,
.rspeed = 166666666,
.multi = 2.5,
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0852,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 15,
.mem_write_cycles = 15,
.cache_read_cycles = 7,
.cache_write_cycles = 7,
.atclk_div = 20
},
{
.name = "187.5 (PR233)",
.cpu_type = CPU_Cx6x86MX,
.fpus = fpus_internal,
.rspeed = 187500000,
.multi = 2.5,
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0852,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 15,
.mem_write_cycles = 15,
.cache_read_cycles = 7,
.cache_write_cycles = 7,
.atclk_div = 45/2
},
{
.name = "208.3 (PR266)",
.cpu_type = CPU_Cx6x86MX,
.fpus = fpus_internal,
.rspeed = 208333333,
.multi = 2.5,
.voltage = 2700,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0852,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 17,
.mem_write_cycles = 17,
.cache_read_cycles = 7,
.cache_write_cycles = 7,
.atclk_div = 25
},
{
.name = "233 (PR300)",
.cpu_type = CPU_Cx6x86MX,
@@ -6375,7 +6443,7 @@ const cpu_family_t cpu_families[] = {
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0852,
.cyrix_id = 0x0854,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 21,
.mem_write_cycles = 21,
@@ -6409,7 +6477,7 @@ const cpu_family_t cpu_families[] = {
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0853,
.cyrix_id = 0x0852,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 23,
.mem_write_cycles = 23,
@@ -6417,6 +6485,23 @@ const cpu_family_t cpu_families[] = {
.cache_write_cycles = 7,
.atclk_div = 30
},
{
.name = "270 (PR350)",
.cpu_type = CPU_Cx6x86MX,
.fpus = fpus_internal,
.rspeed = 270000000,
.multi = 3.0,
.voltage = 2900,
.edx_reset = 0x601,
.cpuid_model = 0x601,
.cyrix_id = 0x0853,
.cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC,
.mem_read_cycles = 25,
.mem_write_cycles = 25,
.cache_read_cycles = 8,
.cache_write_cycles = 8,
.atclk_div = 32
},
{
.name = "285 (PR400)",
.cpu_type = CPU_Cx6x86MX,

826
src/cpu/i8080.c Normal file
View File

@@ -0,0 +1,826 @@
/*
* 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.
*
* Intel 8080 CPU emulation
*
* Authors: Cacodemon345
* Nicolas Allemand
*
* Copyright (c) 2018 Nicolas Allemand
* Copyright (c) 2024 Cacodemon345
*
*/
#include "i8080.h"
#include <stdint.h>
// Changes from upstream:
// Add CALLN and RETEM instructions.
// Add code for instruction fetches.
// this array defines the number of cycles one opcode takes.
// note that there are some special cases: conditional RETs and CALLs
// add +6 cycles if the condition is met
// clang-format off
static const uint8_t OPCODES_CYCLES[256] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 0
4, 10, 7, 5, 5, 5, 7, 4, 4, 10, 7, 5, 5, 5, 7, 4, // 1
4, 10, 16, 5, 5, 5, 7, 4, 4, 10, 16, 5, 5, 5, 7, 4, // 2
4, 10, 13, 5, 10, 10, 10, 4, 4, 10, 13, 5, 5, 5, 7, 4, // 3
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 4
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 5
5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5, // 6
7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5, // 7
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // C
5, 10, 10, 10, 11, 11, 7, 11, 5, 10, 10, 10, 11, 17, 7, 11, // D
5, 10, 10, 18, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11, // E
5, 10, 10, 4, 11, 11, 7, 11, 5, 5, 10, 4, 11, 17, 7, 11 // F
};
// clang-format on
static const char* DISASSEMBLE_TABLE[] = {"nop", "lxi b,#", "stax b", "inx b",
"inr b", "dcr b", "mvi b,#", "rlc", "ill", "dad b", "ldax b", "dcx b",
"inr c", "dcr c", "mvi c,#", "rrc", "ill", "lxi d,#", "stax d", "inx d",
"inr d", "dcr d", "mvi d,#", "ral", "ill", "dad d", "ldax d", "dcx d",
"inr e", "dcr e", "mvi e,#", "rar", "ill", "lxi h,#", "shld", "inx h",
"inr h", "dcr h", "mvi h,#", "daa", "ill", "dad h", "lhld", "dcx h",
"inr l", "dcr l", "mvi l,#", "cma", "ill", "lxi sp,#", "sta $", "inx sp",
"inr M", "dcr M", "mvi M,#", "stc", "ill", "dad sp", "lda $", "dcx sp",
"inr a", "dcr a", "mvi a,#", "cmc", "mov b,b", "mov b,c", "mov b,d",
"mov b,e", "mov b,h", "mov b,l", "mov b,M", "mov b,a", "mov c,b", "mov c,c",
"mov c,d", "mov c,e", "mov c,h", "mov c,l", "mov c,M", "mov c,a", "mov d,b",
"mov d,c", "mov d,d", "mov d,e", "mov d,h", "mov d,l", "mov d,M", "mov d,a",
"mov e,b", "mov e,c", "mov e,d", "mov e,e", "mov e,h", "mov e,l", "mov e,M",
"mov e,a", "mov h,b", "mov h,c", "mov h,d", "mov h,e", "mov h,h", "mov h,l",
"mov h,M", "mov h,a", "mov l,b", "mov l,c", "mov l,d", "mov l,e", "mov l,h",
"mov l,l", "mov l,M", "mov l,a", "mov M,b", "mov M,c", "mov M,d", "mov M,e",
"mov M,h", "mov M,l", "hlt", "mov M,a", "mov a,b", "mov a,c", "mov a,d",
"mov a,e", "mov a,h", "mov a,l", "mov a,M", "mov a,a", "add b", "add c",
"add d", "add e", "add h", "add l", "add M", "add a", "adc b", "adc c",
"adc d", "adc e", "adc h", "adc l", "adc M", "adc a", "sub b", "sub c",
"sub d", "sub e", "sub h", "sub l", "sub M", "sub a", "sbb b", "sbb c",
"sbb d", "sbb e", "sbb h", "sbb l", "sbb M", "sbb a", "ana b", "ana c",
"ana d", "ana e", "ana h", "ana l", "ana M", "ana a", "xra b", "xra c",
"xra d", "xra e", "xra h", "xra l", "xra M", "xra a", "ora b", "ora c",
"ora d", "ora e", "ora h", "ora l", "ora M", "ora a", "cmp b", "cmp c",
"cmp d", "cmp e", "cmp h", "cmp l", "cmp M", "cmp a", "rnz", "pop b",
"jnz $", "jmp $", "cnz $", "push b", "adi #", "rst 0", "rz", "ret", "jz $",
"ill", "cz $", "call $", "aci #", "rst 1", "rnc", "pop d", "jnc $", "out p",
"cnc $", "push d", "sui #", "rst 2", "rc", "ill", "jc $", "in p", "cc $",
"ill", "sbi #", "rst 3", "rpo", "pop h", "jpo $", "xthl", "cpo $", "push h",
"ani #", "rst 4", "rpe", "pchl", "jpe $", "xchg", "cpe $", "ill", "xri #",
"rst 5", "rp", "pop psw", "jp $", "di", "cp $", "push psw", "ori #",
"rst 6", "rm", "sphl", "jm $", "ei", "cm $", "ill", "cpi #", "rst 7"};
#define SET_ZSP(c, val) \
do { \
c->zf = (val) == 0; \
c->sf = (val) >> 7; \
c->pf = parity(val); \
} while (0)
// memory helpers (the only four to use `read_byte` and `write_byte` function
// pointers)
// reads a byte from memory
static inline uint8_t i8080_rb(i8080* const c, uint16_t addr) {
return c->read_byte(c->userdata, addr);
}
// writes a byte to memory
static inline void i8080_wb(i8080* const c, uint16_t addr, uint8_t val) {
c->write_byte(c->userdata, addr, val);
}
// reads a word from memory
static inline uint16_t i8080_rw(i8080* const c, uint16_t addr) {
return c->read_byte(c->userdata, addr + 1) << 8 |
c->read_byte(c->userdata, addr);
}
// writes a word to memory
static inline void i8080_ww(i8080* const c, uint16_t addr, uint16_t val) {
c->write_byte(c->userdata, addr, val & 0xFF);
c->write_byte(c->userdata, addr + 1, val >> 8);
}
// returns the next byte in memory (and updates the program counter)
static inline uint8_t i8080_next_byte(i8080* const c) {
return c->read_byte_seg ? (c->read_byte_seg(c->userdata, c->pc++)) : i8080_rb(c, c->pc++);
}
// returns the next word in memory (and updates the program counter)
static inline uint16_t i8080_next_word(i8080* const c) {
uint16_t result = 0;
if (c->read_byte_seg)
result = c->read_byte_seg(c, c->pc) | (c->read_byte_seg(c, c->pc + 1) << 8);
else
result = i8080_rw(c, c->pc);
c->pc += 2;
return result;
}
// paired registers helpers (setters and getters)
static inline void i8080_set_bc(i8080* const c, uint16_t val) {
c->b = val >> 8;
c->c = val & 0xFF;
}
static inline void i8080_set_de(i8080* const c, uint16_t val) {
c->d = val >> 8;
c->e = val & 0xFF;
}
static inline void i8080_set_hl(i8080* const c, uint16_t val) {
c->h = val >> 8;
c->l = val & 0xFF;
}
static inline uint16_t i8080_get_bc(i8080* const c) {
return (c->b << 8) | c->c;
}
static inline uint16_t i8080_get_de(i8080* const c) {
return (c->d << 8) | c->e;
}
static inline uint16_t i8080_get_hl(i8080* const c) {
return (c->h << 8) | c->l;
}
// stack helpers
// pushes a value into the stack and updates the stack pointer
static inline void i8080_push_stack(i8080* const c, uint16_t val) {
c->sp -= 2;
i8080_ww(c, c->sp, val);
}
// pops a value from the stack and updates the stack pointer
static inline uint16_t i8080_pop_stack(i8080* const c) {
uint16_t val = i8080_rw(c, c->sp);
c->sp += 2;
return val;
}
// opcodes
// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1
static inline bool parity(uint8_t val) {
uint8_t nb_one_bits = 0;
for (int i = 0; i < 8; i++) {
nb_one_bits += ((val >> i) & 1);
}
return (nb_one_bits & 1) == 0;
}
// returns if there was a carry between bit "bit_no" and "bit_no - 1" when
// executing "a + b + cy"
static inline bool carry(int bit_no, uint8_t a, uint8_t b, bool cy) {
int16_t result = a + b + cy;
int16_t carry = result ^ a ^ b;
return carry & (1 << bit_no);
}
// adds a value (+ an optional carry flag) to a register
static inline void i8080_add(
i8080* const c, uint8_t* const reg, uint8_t val, bool cy) {
uint8_t result = *reg + val + cy;
c->cf = carry(8, *reg, val, cy);
c->hf = carry(4, *reg, val, cy);
SET_ZSP(c, result);
*reg = result;
}
// substracts a byte (+ an optional carry flag) from a register
// see https://stackoverflow.com/a/8037485
static inline void i8080_sub(
i8080* const c, uint8_t* const reg, uint8_t val, bool cy) {
i8080_add(c, reg, ~val, !cy);
c->cf = !c->cf;
}
// adds a word to HL
static inline void i8080_dad(i8080* const c, uint16_t val) {
c->cf = ((i8080_get_hl(c) + val) >> 16) & 1;
i8080_set_hl(c, i8080_get_hl(c) + val);
}
// increments a byte
static inline uint8_t i8080_inr(i8080* const c, uint8_t val) {
uint8_t result = val + 1;
c->hf = (result & 0xF) == 0;
SET_ZSP(c, result);
return result;
}
// decrements a byte
static inline uint8_t i8080_dcr(i8080* const c, uint8_t val) {
uint8_t result = val - 1;
c->hf = !((result & 0xF) == 0xF);
SET_ZSP(c, result);
return result;
}
// executes a logic "and" between register A and a byte, then stores the
// result in register A
static inline void i8080_ana(i8080* const c, uint8_t val) {
uint8_t result = c->a & val;
c->cf = 0;
c->hf = ((c->a | val) & 0x08) != 0;
SET_ZSP(c, result);
c->a = result;
}
// executes a logic "xor" between register A and a byte, then stores the
// result in register A
static inline void i8080_xra(i8080* const c, uint8_t val) {
c->a ^= val;
c->cf = 0;
c->hf = 0;
SET_ZSP(c, c->a);
}
// executes a logic "or" between register A and a byte, then stores the
// result in register A
static inline void i8080_ora(i8080* const c, uint8_t val) {
c->a |= val;
c->cf = 0;
c->hf = 0;
SET_ZSP(c, c->a);
}
// compares the register A to another byte
static inline void i8080_cmp(i8080* const c, uint8_t val) {
int16_t result = c->a - val;
c->cf = result >> 8;
c->hf = ~(c->a ^ result ^ val) & 0x10;
SET_ZSP(c, result & 0xFF);
}
// sets the program counter to a given address
static inline void i8080_jmp(i8080* const c, uint16_t addr) {
c->pc = addr;
}
// jumps to next address pointed by the next word in memory if a condition
// is met
static inline void i8080_cond_jmp(i8080* const c, bool condition) {
uint16_t addr = i8080_next_word(c);
if (condition) {
c->pc = addr;
}
}
// pushes the current pc to the stack, then jumps to an address
static inline void i8080_call(i8080* const c, uint16_t addr) {
i8080_push_stack(c, c->pc);
i8080_jmp(c, addr);
}
// calls to next word in memory if a condition is met
static inline void i8080_cond_call(i8080* const c, bool condition) {
uint16_t addr = i8080_next_word(c);
if (condition) {
i8080_call(c, addr);
c->cyc += 6;
}
}
// returns from subroutine
static inline void i8080_ret(i8080* const c) {
c->pc = i8080_pop_stack(c);
}
// returns from subroutine if a condition is met
static inline void i8080_cond_ret(i8080* const c, bool condition) {
if (condition) {
i8080_ret(c);
c->cyc += 6;
}
}
// pushes register A and the flags into the stack
static inline void i8080_push_psw(i8080* const c) {
// note: bit 3 and 5 are always 0
uint8_t psw = 0;
psw |= c->sf << 7;
psw |= c->zf << 6;
psw |= c->hf << 4;
psw |= c->pf << 2;
psw |= 1 << 1; // bit 1 is always 1
psw |= c->cf << 0;
i8080_push_stack(c, c->a << 8 | psw);
}
// pops register A and the flags from the stack
static inline void i8080_pop_psw(i8080* const c) {
uint16_t af = i8080_pop_stack(c);
c->a = af >> 8;
uint8_t psw = af & 0xFF;
c->sf = (psw >> 7) & 1;
c->zf = (psw >> 6) & 1;
c->hf = (psw >> 4) & 1;
c->pf = (psw >> 2) & 1;
c->cf = (psw >> 0) & 1;
}
// rotate register A left
static inline void i8080_rlc(i8080* const c) {
c->cf = c->a >> 7;
c->a = (c->a << 1) | c->cf;
}
// rotate register A right
static inline void i8080_rrc(i8080* const c) {
c->cf = c->a & 1;
c->a = (c->a >> 1) | (c->cf << 7);
}
// rotate register A left with the carry flag
static inline void i8080_ral(i8080* const c) {
bool cy = c->cf;
c->cf = c->a >> 7;
c->a = (c->a << 1) | cy;
}
// rotate register A right with the carry flag
static inline void i8080_rar(i8080* const c) {
bool cy = c->cf;
c->cf = c->a & 1;
c->a = (c->a >> 1) | (cy << 7);
}
// Decimal Adjust Accumulator: the eight-bit number in register A is adjusted
// to form two four-bit binary-coded-decimal digits.
// For example, if A=$2B and DAA is executed, A becomes $31.
static inline void i8080_daa(i8080* const c) {
bool cy = c->cf;
uint8_t correction = 0;
uint8_t lsb = c->a & 0x0F;
uint8_t msb = c->a >> 4;
if (c->hf || lsb > 9) {
correction += 0x06;
}
if (c->cf || msb > 9 || (msb >= 9 && lsb > 9)) {
correction += 0x60;
cy = 1;
}
i8080_add(c, &c->a, correction, 0);
c->cf = cy;
}
// switches the value of registers DE and HL
static inline void i8080_xchg(i8080* const c) {
uint16_t de = i8080_get_de(c);
i8080_set_de(c, i8080_get_hl(c));
i8080_set_hl(c, de);
}
// switches the value of a word at (sp) and HL
static inline void i8080_xthl(i8080* const c) {
uint16_t val = i8080_rw(c, c->sp);
i8080_ww(c, c->sp, i8080_get_hl(c));
i8080_set_hl(c, val);
}
extern void interrupt_808x(uint16_t addr);
extern void retem_i8080(void);
// executes one opcode
static inline void i8080_execute(i8080* const c, uint8_t opcode) {
c->cyc += OPCODES_CYCLES[opcode];
// when DI is executed, interrupts won't be serviced
// until the end of next instruction:
if (c->interrupt_delay > 0) {
c->interrupt_delay -= 1;
}
switch (opcode) {
case 0x7F: c->a = c->a; break; // MOV A,A
case 0x78: c->a = c->b; break; // MOV A,B
case 0x79: c->a = c->c; break; // MOV A,C
case 0x7A: c->a = c->d; break; // MOV A,D
case 0x7B: c->a = c->e; break; // MOV A,E
case 0x7C: c->a = c->h; break; // MOV A,H
case 0x7D: c->a = c->l; break; // MOV A,L
case 0x7E: c->a = i8080_rb(c, i8080_get_hl(c)); break; // MOV A,M
case 0x0A: c->a = i8080_rb(c, i8080_get_bc(c)); break; // LDAX B
case 0x1A: c->a = i8080_rb(c, i8080_get_de(c)); break; // LDAX D
case 0x3A: c->a = i8080_rb(c, i8080_next_word(c)); break; // LDA word
case 0x47: c->b = c->a; break; // MOV B,A
case 0x40: c->b = c->b; break; // MOV B,B
case 0x41: c->b = c->c; break; // MOV B,C
case 0x42: c->b = c->d; break; // MOV B,D
case 0x43: c->b = c->e; break; // MOV B,E
case 0x44: c->b = c->h; break; // MOV B,H
case 0x45: c->b = c->l; break; // MOV B,L
case 0x46: c->b = i8080_rb(c, i8080_get_hl(c)); break; // MOV B,M
case 0x4F: c->c = c->a; break; // MOV C,A
case 0x48: c->c = c->b; break; // MOV C,B
case 0x49: c->c = c->c; break; // MOV C,C
case 0x4A: c->c = c->d; break; // MOV C,D
case 0x4B: c->c = c->e; break; // MOV C,E
case 0x4C: c->c = c->h; break; // MOV C,H
case 0x4D: c->c = c->l; break; // MOV C,L
case 0x4E: c->c = i8080_rb(c, i8080_get_hl(c)); break; // MOV C,M
case 0x57: c->d = c->a; break; // MOV D,A
case 0x50: c->d = c->b; break; // MOV D,B
case 0x51: c->d = c->c; break; // MOV D,C
case 0x52: c->d = c->d; break; // MOV D,D
case 0x53: c->d = c->e; break; // MOV D,E
case 0x54: c->d = c->h; break; // MOV D,H
case 0x55: c->d = c->l; break; // MOV D,L
case 0x56: c->d = i8080_rb(c, i8080_get_hl(c)); break; // MOV D,M
case 0x5F: c->e = c->a; break; // MOV E,A
case 0x58: c->e = c->b; break; // MOV E,B
case 0x59: c->e = c->c; break; // MOV E,C
case 0x5A: c->e = c->d; break; // MOV E,D
case 0x5B: c->e = c->e; break; // MOV E,E
case 0x5C: c->e = c->h; break; // MOV E,H
case 0x5D: c->e = c->l; break; // MOV E,L
case 0x5E: c->e = i8080_rb(c, i8080_get_hl(c)); break; // MOV E,M
case 0x67: c->h = c->a; break; // MOV H,A
case 0x60: c->h = c->b; break; // MOV H,B
case 0x61: c->h = c->c; break; // MOV H,C
case 0x62: c->h = c->d; break; // MOV H,D
case 0x63: c->h = c->e; break; // MOV H,E
case 0x64: c->h = c->h; break; // MOV H,H
case 0x65: c->h = c->l; break; // MOV H,L
case 0x66: c->h = i8080_rb(c, i8080_get_hl(c)); break; // MOV H,M
case 0x6F: c->l = c->a; break; // MOV L,A
case 0x68: c->l = c->b; break; // MOV L,B
case 0x69: c->l = c->c; break; // MOV L,C
case 0x6A: c->l = c->d; break; // MOV L,D
case 0x6B: c->l = c->e; break; // MOV L,E
case 0x6C: c->l = c->h; break; // MOV L,H
case 0x6D: c->l = c->l; break; // MOV L,L
case 0x6E: c->l = i8080_rb(c, i8080_get_hl(c)); break; // MOV L,M
case 0x77: i8080_wb(c, i8080_get_hl(c), c->a); break; // MOV M,A
case 0x70: i8080_wb(c, i8080_get_hl(c), c->b); break; // MOV M,B
case 0x71: i8080_wb(c, i8080_get_hl(c), c->c); break; // MOV M,C
case 0x72: i8080_wb(c, i8080_get_hl(c), c->d); break; // MOV M,D
case 0x73: i8080_wb(c, i8080_get_hl(c), c->e); break; // MOV M,E
case 0x74: i8080_wb(c, i8080_get_hl(c), c->h); break; // MOV M,H
case 0x75: i8080_wb(c, i8080_get_hl(c), c->l); break; // MOV M,L
case 0x3E: c->a = i8080_next_byte(c); break; // MVI A,byte
case 0x06: c->b = i8080_next_byte(c); break; // MVI B,byte
case 0x0E: c->c = i8080_next_byte(c); break; // MVI C,byte
case 0x16: c->d = i8080_next_byte(c); break; // MVI D,byte
case 0x1E: c->e = i8080_next_byte(c); break; // MVI E,byte
case 0x26: c->h = i8080_next_byte(c); break; // MVI H,byte
case 0x2E: c->l = i8080_next_byte(c); break; // MVI L,byte
case 0x36:
i8080_wb(c, i8080_get_hl(c), i8080_next_byte(c));
break; // MVI M,byte
case 0x02: i8080_wb(c, i8080_get_bc(c), c->a); break; // STAX B
case 0x12: i8080_wb(c, i8080_get_de(c), c->a); break; // STAX D
case 0x32: i8080_wb(c, i8080_next_word(c), c->a); break; // STA word
case 0x01: i8080_set_bc(c, i8080_next_word(c)); break; // LXI B,word
case 0x11: i8080_set_de(c, i8080_next_word(c)); break; // LXI D,word
case 0x21: i8080_set_hl(c, i8080_next_word(c)); break; // LXI H,word
case 0x31: c->sp = i8080_next_word(c); break; // LXI SP,word
case 0x2A: i8080_set_hl(c, i8080_rw(c, i8080_next_word(c))); break; // LHLD
case 0x22: i8080_ww(c, i8080_next_word(c), i8080_get_hl(c)); break; // SHLD
case 0xF9: c->sp = i8080_get_hl(c); break; // SPHL
case 0xEB: i8080_xchg(c); break; // XCHG
case 0xE3: i8080_xthl(c); break; // XTHL
case 0x87: i8080_add(c, &c->a, c->a, 0); break; // ADD A
case 0x80: i8080_add(c, &c->a, c->b, 0); break; // ADD B
case 0x81: i8080_add(c, &c->a, c->c, 0); break; // ADD C
case 0x82: i8080_add(c, &c->a, c->d, 0); break; // ADD D
case 0x83: i8080_add(c, &c->a, c->e, 0); break; // ADD E
case 0x84: i8080_add(c, &c->a, c->h, 0); break; // ADD H
case 0x85: i8080_add(c, &c->a, c->l, 0); break; // ADD L
case 0x86:
i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0);
break; // ADD M
case 0xC6: i8080_add(c, &c->a, i8080_next_byte(c), 0); break; // ADI byte
case 0x8F: i8080_add(c, &c->a, c->a, c->cf); break; // ADC A
case 0x88: i8080_add(c, &c->a, c->b, c->cf); break; // ADC B
case 0x89: i8080_add(c, &c->a, c->c, c->cf); break; // ADC C
case 0x8A: i8080_add(c, &c->a, c->d, c->cf); break; // ADC D
case 0x8B: i8080_add(c, &c->a, c->e, c->cf); break; // ADC E
case 0x8C: i8080_add(c, &c->a, c->h, c->cf); break; // ADC H
case 0x8D: i8080_add(c, &c->a, c->l, c->cf); break; // ADC L
case 0x8E:
i8080_add(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf);
break; // ADC M
case 0xCE: i8080_add(c, &c->a, i8080_next_byte(c), c->cf); break; // ACI byte
case 0x97: i8080_sub(c, &c->a, c->a, 0); break; // SUB A
case 0x90: i8080_sub(c, &c->a, c->b, 0); break; // SUB B
case 0x91: i8080_sub(c, &c->a, c->c, 0); break; // SUB C
case 0x92: i8080_sub(c, &c->a, c->d, 0); break; // SUB D
case 0x93: i8080_sub(c, &c->a, c->e, 0); break; // SUB E
case 0x94: i8080_sub(c, &c->a, c->h, 0); break; // SUB H
case 0x95: i8080_sub(c, &c->a, c->l, 0); break; // SUB L
case 0x96:
i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), 0);
break; // SUB M
case 0xD6: i8080_sub(c, &c->a, i8080_next_byte(c), 0); break; // SUI byte
case 0x9F: i8080_sub(c, &c->a, c->a, c->cf); break; // SBB A
case 0x98: i8080_sub(c, &c->a, c->b, c->cf); break; // SBB B
case 0x99: i8080_sub(c, &c->a, c->c, c->cf); break; // SBB C
case 0x9A: i8080_sub(c, &c->a, c->d, c->cf); break; // SBB D
case 0x9B: i8080_sub(c, &c->a, c->e, c->cf); break; // SBB E
case 0x9C: i8080_sub(c, &c->a, c->h, c->cf); break; // SBB H
case 0x9D: i8080_sub(c, &c->a, c->l, c->cf); break; // SBB L
case 0x9E:
i8080_sub(c, &c->a, i8080_rb(c, i8080_get_hl(c)), c->cf);
break; // SBB M
case 0xDE: i8080_sub(c, &c->a, i8080_next_byte(c), c->cf); break; // SBI byte
case 0x09: i8080_dad(c, i8080_get_bc(c)); break; // DAD B
case 0x19: i8080_dad(c, i8080_get_de(c)); break; // DAD D
case 0x29: i8080_dad(c, i8080_get_hl(c)); break; // DAD H
case 0x39: i8080_dad(c, c->sp); break; // DAD SP
case 0xF3: c->iff = 0; break; // DI
case 0xFB:
c->iff = 1;
c->interrupt_delay = 1;
break; // EI
case 0x00: break; // NOP
case 0x76: c->halted = 1; break; // HLT
case 0x3C: c->a = i8080_inr(c, c->a); break; // INR A
case 0x04: c->b = i8080_inr(c, c->b); break; // INR B
case 0x0C: c->c = i8080_inr(c, c->c); break; // INR C
case 0x14: c->d = i8080_inr(c, c->d); break; // INR D
case 0x1C: c->e = i8080_inr(c, c->e); break; // INR E
case 0x24: c->h = i8080_inr(c, c->h); break; // INR H
case 0x2C: c->l = i8080_inr(c, c->l); break; // INR L
case 0x34:
i8080_wb(c, i8080_get_hl(c), i8080_inr(c, i8080_rb(c, i8080_get_hl(c))));
break; // INR M
case 0x3D: c->a = i8080_dcr(c, c->a); break; // DCR A
case 0x05: c->b = i8080_dcr(c, c->b); break; // DCR B
case 0x0D: c->c = i8080_dcr(c, c->c); break; // DCR C
case 0x15: c->d = i8080_dcr(c, c->d); break; // DCR D
case 0x1D: c->e = i8080_dcr(c, c->e); break; // DCR E
case 0x25: c->h = i8080_dcr(c, c->h); break; // DCR H
case 0x2D: c->l = i8080_dcr(c, c->l); break; // DCR L
case 0x35:
i8080_wb(c, i8080_get_hl(c), i8080_dcr(c, i8080_rb(c, i8080_get_hl(c))));
break; // DCR M
case 0x03: i8080_set_bc(c, i8080_get_bc(c) + 1); break; // INX B
case 0x13: i8080_set_de(c, i8080_get_de(c) + 1); break; // INX D
case 0x23: i8080_set_hl(c, i8080_get_hl(c) + 1); break; // INX H
case 0x33: c->sp += 1; break; // INX SP
case 0x0B: i8080_set_bc(c, i8080_get_bc(c) - 1); break; // DCX B
case 0x1B: i8080_set_de(c, i8080_get_de(c) - 1); break; // DCX D
case 0x2B: i8080_set_hl(c, i8080_get_hl(c) - 1); break; // DCX H
case 0x3B: c->sp -= 1; break; // DCX SP
case 0x27: i8080_daa(c); break; // DAA
case 0x2F: c->a = ~c->a; break; // CMA
case 0x37: c->cf = 1; break; // STC
case 0x3F: c->cf = !c->cf; break; // CMC
case 0x07: i8080_rlc(c); break; // RLC (rotate left)
case 0x0F: i8080_rrc(c); break; // RRC (rotate right)
case 0x17: i8080_ral(c); break; // RAL
case 0x1F: i8080_rar(c); break; // RAR
case 0xA7: i8080_ana(c, c->a); break; // ANA A
case 0xA0: i8080_ana(c, c->b); break; // ANA B
case 0xA1: i8080_ana(c, c->c); break; // ANA C
case 0xA2: i8080_ana(c, c->d); break; // ANA D
case 0xA3: i8080_ana(c, c->e); break; // ANA E
case 0xA4: i8080_ana(c, c->h); break; // ANA H
case 0xA5: i8080_ana(c, c->l); break; // ANA L
case 0xA6: i8080_ana(c, i8080_rb(c, i8080_get_hl(c))); break; // ANA M
case 0xE6: i8080_ana(c, i8080_next_byte(c)); break; // ANI byte
case 0xAF: i8080_xra(c, c->a); break; // XRA A
case 0xA8: i8080_xra(c, c->b); break; // XRA B
case 0xA9: i8080_xra(c, c->c); break; // XRA C
case 0xAA: i8080_xra(c, c->d); break; // XRA D
case 0xAB: i8080_xra(c, c->e); break; // XRA E
case 0xAC: i8080_xra(c, c->h); break; // XRA H
case 0xAD: i8080_xra(c, c->l); break; // XRA L
case 0xAE: i8080_xra(c, i8080_rb(c, i8080_get_hl(c))); break; // XRA M
case 0xEE: i8080_xra(c, i8080_next_byte(c)); break; // XRI byte
case 0xB7: i8080_ora(c, c->a); break; // ORA A
case 0xB0: i8080_ora(c, c->b); break; // ORA B
case 0xB1: i8080_ora(c, c->c); break; // ORA C
case 0xB2: i8080_ora(c, c->d); break; // ORA D
case 0xB3: i8080_ora(c, c->e); break; // ORA E
case 0xB4: i8080_ora(c, c->h); break; // ORA H
case 0xB5: i8080_ora(c, c->l); break; // ORA L
case 0xB6: i8080_ora(c, i8080_rb(c, i8080_get_hl(c))); break; // ORA M
case 0xF6: i8080_ora(c, i8080_next_byte(c)); break; // ORI byte
case 0xBF: i8080_cmp(c, c->a); break; // CMP A
case 0xB8: i8080_cmp(c, c->b); break; // CMP B
case 0xB9: i8080_cmp(c, c->c); break; // CMP C
case 0xBA: i8080_cmp(c, c->d); break; // CMP D
case 0xBB: i8080_cmp(c, c->e); break; // CMP E
case 0xBC: i8080_cmp(c, c->h); break; // CMP H
case 0xBD: i8080_cmp(c, c->l); break; // CMP L
case 0xBE: i8080_cmp(c, i8080_rb(c, i8080_get_hl(c))); break; // CMP M
case 0xFE: i8080_cmp(c, i8080_next_byte(c)); break; // CPI byte
case 0xC3: i8080_jmp(c, i8080_next_word(c)); break; // JMP
case 0xC2: i8080_cond_jmp(c, c->zf == 0); break; // JNZ
case 0xCA: i8080_cond_jmp(c, c->zf == 1); break; // JZ
case 0xD2: i8080_cond_jmp(c, c->cf == 0); break; // JNC
case 0xDA: i8080_cond_jmp(c, c->cf == 1); break; // JC
case 0xE2: i8080_cond_jmp(c, c->pf == 0); break; // JPO
case 0xEA: i8080_cond_jmp(c, c->pf == 1); break; // JPE
case 0xF2: i8080_cond_jmp(c, c->sf == 0); break; // JP
case 0xFA: i8080_cond_jmp(c, c->sf == 1); break; // JM
case 0xE9: c->pc = i8080_get_hl(c); break; // PCHL
case 0xCD: i8080_call(c, i8080_next_word(c)); break; // CALL
case 0xC4: i8080_cond_call(c, c->zf == 0); break; // CNZ
case 0xCC: i8080_cond_call(c, c->zf == 1); break; // CZ
case 0xD4: i8080_cond_call(c, c->cf == 0); break; // CNC
case 0xDC: i8080_cond_call(c, c->cf == 1); break; // CC
case 0xE4: i8080_cond_call(c, c->pf == 0); break; // CPO
case 0xEC: i8080_cond_call(c, c->pf == 1); break; // CPE
case 0xF4: i8080_cond_call(c, c->sf == 0); break; // CP
case 0xFC: i8080_cond_call(c, c->sf == 1); break; // CM
case 0xC9: i8080_ret(c); break; // RET
case 0xC0: i8080_cond_ret(c, c->zf == 0); break; // RNZ
case 0xC8: i8080_cond_ret(c, c->zf == 1); break; // RZ
case 0xD0: i8080_cond_ret(c, c->cf == 0); break; // RNC
case 0xD8: i8080_cond_ret(c, c->cf == 1); break; // RC
case 0xE0: i8080_cond_ret(c, c->pf == 0); break; // RPO
case 0xE8: i8080_cond_ret(c, c->pf == 1); break; // RPE
case 0xF0: i8080_cond_ret(c, c->sf == 0); break; // RP
case 0xF8: i8080_cond_ret(c, c->sf == 1); break; // RM
case 0xC7: i8080_call(c, 0x00); break; // RST 0
case 0xCF: i8080_call(c, 0x08); break; // RST 1
case 0xD7: i8080_call(c, 0x10); break; // RST 2
case 0xDF: i8080_call(c, 0x18); break; // RST 3
case 0xE7: i8080_call(c, 0x20); break; // RST 4
case 0xEF: i8080_call(c, 0x28); break; // RST 5
case 0xF7: i8080_call(c, 0x30); break; // RST 6
case 0xFF: i8080_call(c, 0x38); break; // RST 7
case 0xC5: i8080_push_stack(c, i8080_get_bc(c)); break; // PUSH B
case 0xD5: i8080_push_stack(c, i8080_get_de(c)); break; // PUSH D
case 0xE5: i8080_push_stack(c, i8080_get_hl(c)); break; // PUSH H
case 0xF5: i8080_push_psw(c); break; // PUSH PSW
case 0xC1: i8080_set_bc(c, i8080_pop_stack(c)); break; // POP B
case 0xD1: i8080_set_de(c, i8080_pop_stack(c)); break; // POP D
case 0xE1: i8080_set_hl(c, i8080_pop_stack(c)); break; // POP H
case 0xF1: i8080_pop_psw(c); break; // POP PSW
case 0xDB: c->a = c->port_in(c->userdata, i8080_next_byte(c)); break; // IN
case 0xD3: c->port_out(c->userdata, i8080_next_byte(c), c->a); break; // OUT
case 0x08:
case 0x10:
case 0x18:
case 0x20:
case 0x28:
case 0x30:
case 0x38: break; // undocumented NOPs
case 0xD9: i8080_ret(c); break; // undocumented RET
case 0xDD:
case 0xED:
{
if (opcode == 0xED) {
uint8_t data = i8080_next_byte(c);
if (data == 0xED) {
interrupt_808x(i8080_next_byte(c));
break;
} else if (data == 0xFD) {
retem_i8080();
break;
}
else {
i8080_call(c, (i8080_next_byte(c) << 8) | data); break;
}
}
}
case 0xFD: i8080_call(c, i8080_next_word(c)); break; // undocumented CALLs
case 0xCB: i8080_jmp(c, i8080_next_word(c)); break; // undocumented JMP
}
}
// initialises the emulator with default values
void i8080_init(i8080* const c) {
c->read_byte = NULL;
c->write_byte = NULL;
c->port_in = NULL;
c->port_out = NULL;
c->userdata = NULL;
c->cyc = 0;
c->pc = 0;
c->sp = 0;
c->a = 0;
c->b = 0;
c->c = 0;
c->d = 0;
c->e = 0;
c->h = 0;
c->l = 0;
c->sf = 0;
c->zf = 0;
c->hf = 0;
c->pf = 0;
c->cf = 0;
c->iff = 0;
c->halted = 0;
c->interrupt_pending = 0;
c->interrupt_vector = 0;
c->interrupt_delay = 0;
}
// executes one instruction
void i8080_step(i8080* const c) {
// interrupt processing: if an interrupt is pending and IFF is set,
// we execute the interrupt vector passed by the user.
if (c->interrupt_pending && c->iff && c->interrupt_delay == 0) {
c->interrupt_pending = 0;
c->iff = 0;
c->halted = 0;
i8080_execute(c, c->interrupt_vector);
} else if (!c->halted) {
i8080_execute(c, i8080_next_byte(c));
}
}
// asks for an interrupt to be serviced
void i8080_interrupt(i8080* const c, uint8_t opcode) {
c->interrupt_pending = 1;
c->interrupt_vector = opcode;
}
// outputs a debug trace of the emulator state to the standard output,
// including registers and flags
void i8080_debug_output(i8080* const c, bool print_disassembly) {
uint8_t f = 0;
f |= c->sf << 7;
f |= c->zf << 6;
f |= c->hf << 4;
f |= c->pf << 2;
f |= 1 << 1; // bit 1 is always 1
f |= c->cf << 0;
printf("PC: %04X, AF: %04X, BC: %04X, DE: %04X, HL: %04X, SP: %04X, CYC: %lu",
c->pc, c->a << 8 | f, i8080_get_bc(c), i8080_get_de(c), i8080_get_hl(c),
c->sp, c->cyc);
printf("\t(%02X %02X %02X %02X)", i8080_rb(c, c->pc), i8080_rb(c, c->pc + 1),
i8080_rb(c, c->pc + 2), i8080_rb(c, c->pc + 3));
if (print_disassembly) {
printf(" - %s", DISASSEMBLE_TABLE[i8080_rb(c, c->pc)]);
}
printf("\n");
}
#undef SET_ZSP

35
src/cpu/i8080.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef I8080_I8080_H_
#define I8080_I8080_H_
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
typedef struct i8080 {
// memory + io interface
uint8_t (*read_byte)(void*, uint16_t); // user function to read from memory
void (*write_byte)(void*, uint16_t, uint8_t); // same for writing to memory
uint8_t (*read_byte_seg)(void*, uint16_t); // user function to read from memory (Code segment)
uint8_t (*port_in)(void*, uint8_t); // user function to read from port
void (*port_out)(void*, uint8_t, uint8_t); // same for writing to port
void* userdata; // user custom pointer
unsigned long cyc; // cycle count
uint16_t pc, sp; // program counter, stack pointer
uint8_t a, b, c, d, e, h, l; // registers
// flags: sign, zero, half-carry, parity, carry, interrupt flip-flop
bool sf : 1, zf : 1, hf : 1, pf : 1, cf : 1, iff : 1;
bool halted : 1;
bool interrupt_pending : 1;
uint8_t interrupt_vector;
uint8_t interrupt_delay;
} i8080;
void i8080_init(i8080* const c);
void i8080_step(i8080* const c);
void i8080_interrupt(i8080* const c, uint8_t opcode);
void i8080_debug_output(i8080* const c, bool print_disassembly);
#endif // I8080_I8080_H_

View File

@@ -103,4 +103,10 @@ extern int fpu_cycles;
extern void x86illegal(void);
extern uint8_t rep_op;
extern uint8_t is_smint;
extern uint16_t io_port;
extern uint32_t io_val;
#endif /*EMU_X86_H*/

View File

@@ -35,7 +35,13 @@ opSVDC_common(uint32_t fetchdat)
static int
opSVDC_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
opSVDC_common(fetchdat);
@@ -47,7 +53,13 @@ opSVDC_a16(uint32_t fetchdat)
static int
opSVDC_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
opSVDC_common(fetchdat);
@@ -63,18 +75,23 @@ opRSDC_common(uint32_t fetchdat)
switch (rmdat & 0x38) {
case 0x00: /*ES*/
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_es);
ES = readmemw(0, easeg + cpu_state.eaaddr + 8);
break;
case 0x18: /*DS*/
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ds);
DS = readmemw(0, easeg + cpu_state.eaaddr + 8);
break;
case 0x10: /*SS*/
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_ss);
SS = readmemw(0, easeg + cpu_state.eaaddr + 8);
break;
case 0x20: /*FS*/
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_fs);
FS = readmemw(0, easeg + cpu_state.eaaddr + 8);
break;
case 0x28: /*GS*/
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &cpu_state.seg_gs);
GS = readmemw(0, easeg + cpu_state.eaaddr + 8);
break;
default:
x86illegal();
@@ -83,7 +100,13 @@ opRSDC_common(uint32_t fetchdat)
static int
opRSDC_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
opRSDC_common(fetchdat);
@@ -95,7 +118,13 @@ opRSDC_a16(uint32_t fetchdat)
static int
opRSDC_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
opRSDC_common(fetchdat);
@@ -108,7 +137,13 @@ opRSDC_a32(uint32_t fetchdat)
static int
opSVLDT_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
@@ -121,7 +156,13 @@ opSVLDT_a16(uint32_t fetchdat)
static int
opSVLDT_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
@@ -135,7 +176,13 @@ opSVLDT_a32(uint32_t fetchdat)
static int
opRSLDT_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
@@ -147,7 +194,13 @@ opRSLDT_a16(uint32_t fetchdat)
static int
opRSLDT_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cyrix_load_seg_descriptor(easeg + cpu_state.eaaddr, &ldt);
@@ -160,7 +213,13 @@ opRSLDT_a32(uint32_t fetchdat)
static int
opSVTS_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
@@ -173,7 +232,13 @@ opSVTS_a16(uint32_t fetchdat)
static int
opSVTS_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
@@ -187,7 +252,13 @@ opSVTS_a32(uint32_t fetchdat)
static int
opRSTS_a16(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
@@ -200,7 +271,13 @@ opRSTS_a16(uint32_t fetchdat)
static int
opRSTS_a32(uint32_t fetchdat)
{
if (in_smm) {
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
cyrix_write_seg_descriptor(easeg + cpu_state.eaaddr, &tr);
@@ -214,10 +291,16 @@ opRSTS_a32(uint32_t fetchdat)
static int
opSMINT(UNUSED(uint32_t fetchdat))
{
uint8_t ccr1_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) &&
(cyrix.arr[3].size > 0);
if (in_smm)
fatal("opSMINT\n");
else
x86illegal();
else if (ccr1_check) {
is_smint = 1;
enter_smm(0);
}
return 1;
}
@@ -225,9 +308,26 @@ opSMINT(UNUSED(uint32_t fetchdat))
static int
opRDSHR_a16(UNUSED(uint32_t fetchdat))
{
if (in_smm)
fatal("opRDSHR_a16\n");
else
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
if (cpu_mod == 3) {
cpu_state.regs[cpu_rm].l = cyrix.smhr;
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0);
} else {
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(cyrix.smhr);
CLOCK_CYCLES(is486 ? 1 : 2);
PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 0);
}
return cpu_state.abrt;
} else
x86illegal();
return 1;
@@ -235,30 +335,91 @@ opRDSHR_a16(UNUSED(uint32_t fetchdat))
static int
opRDSHR_a32(UNUSED(uint32_t fetchdat))
{
if (in_smm)
fatal("opRDSHR_a32\n");
else
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
if (cpu_mod == 3) {
cpu_state.regs[cpu_rm].l = cyrix.smhr;
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1);
} else {
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(cyrix.smhr);
CLOCK_CYCLES(is486 ? 1 : 2);
PREFETCH_RUN(2, 2, rmdat, 0, 0, 0, 1, 1);
}
return cpu_state.abrt;
} else
x86illegal();
return 1;
}
static int
opWRSHR_a16(UNUSED(uint32_t fetchdat))
opWRSHR_a16(uint32_t fetchdat)
{
if (in_smm)
fatal("opWRSHR_a16\n");
else
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_16(fetchdat);
if (cpu_mod == 3) {
cyrix.smhr = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 0);
} else {
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
temp = geteal();
if (cpu_state.abrt)
return 1;
cyrix.smhr = temp;
CLOCK_CYCLES(is486 ? 1 : 4);
PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 0);
}
return 0;
} else
x86illegal();
return 1;
}
static int
opWRSHR_a32(UNUSED(uint32_t fetchdat))
opWRSHR_a32(uint32_t fetchdat)
{
if (in_smm)
fatal("opWRSHR_a32\n");
else
uint8_t ins_check = ((ccr1 & (CCR1_USE_SMI | CCR1_SM3)) ==
(CCR1_USE_SMI | CCR1_SM3)) &&
((ccr1 & CCR1_SMAC) || in_smm) &&
(cyrix.arr[3].size > 0) &&
(CPL == 0);
if (ins_check) {
fetch_ea_32(fetchdat);
if (cpu_mod == 3) {
cyrix.smhr = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, rmdat, 0, 0, 0, 0, 1);
} else {
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
temp = geteal();
if (cpu_state.abrt)
return 1;
cyrix.smhr = temp;
CLOCK_CYCLES(is486 ? 1 : 4);
PREFETCH_RUN(4, 2, rmdat, 0, 1, 0, 0, 1);
}
return 0;
} else
x86illegal();
return 1;

View File

@@ -184,7 +184,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG))
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001)
flushmmucache();
else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) {
if (is_p6 || cpu_use_dynarec)
@@ -193,7 +193,8 @@ opMOV_CRx_r_a16(uint32_t fetchdat)
flushmmucache_nopc();
cpu_flush_pending = 1;
}
}
} else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG)
flushmmucache_write();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
@@ -249,7 +250,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat)
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG))
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001)
flushmmucache();
else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) {
if (is_p6 || cpu_use_dynarec)
@@ -258,7 +259,8 @@ opMOV_CRx_r_a32(uint32_t fetchdat)
flushmmucache_nopc();
cpu_flush_pending = 1;
}
}
} else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG)
flushmmucache_write();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;

View File

@@ -180,12 +180,13 @@ opMOV_CRx_r_a16(uint32_t fetchdat)
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG))
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001)
flushmmucache();
else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) {
flushmmucache_nopc();
cpu_flush_pending = 1;
}
} else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG)
flushmmucache_write();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
@@ -241,12 +242,13 @@ opMOV_CRx_r_a32(uint32_t fetchdat)
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG))
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x00000001)
flushmmucache();
else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) {
flushmmucache_nopc();
cpu_flush_pending = 1;
}
} else if ((cpu_state.regs[cpu_rm].l ^ cr0) & WP_FLAG)
flushmmucache_write();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;

View File

@@ -855,6 +855,7 @@ opREPNE(uint32_t fetchdat)
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
rep_op = fetchdat & 0xff;
if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
@@ -869,6 +870,7 @@ opREPE(uint32_t fetchdat)
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
rep_op = fetchdat & 0xff;
if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);

View File

@@ -843,6 +843,7 @@ opREPNE(uint32_t fetchdat)
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
rep_op = fetchdat & 0xff;
if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
@@ -857,6 +858,7 @@ opREPE(uint32_t fetchdat)
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
rep_op = fetchdat & 0xff;
if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);

View File

@@ -761,6 +761,7 @@ opREPNE(uint32_t fetchdat)
cpu_state.pc++;
CLOCK_CYCLES(2);
rep_op = fetchdat & 0xff;
if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
@@ -774,6 +775,7 @@ opREPE(uint32_t fetchdat)
cpu_state.pc++;
CLOCK_CYCLES(2);
rep_op = fetchdat & 0xff;
if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);

View File

@@ -1113,7 +1113,7 @@ loadcscall(uint16_t seg)
x86seg_log("Type %04X\n", type);
if (type == 0x0c00) {
PUSHL_SEL(oldss);
is586 ? PUSHL(oldss) : PUSHL_SEL(oldss);
PUSHL(oldsp2);
if (cpu_state.abrt) {
SS = oldss;
@@ -1334,6 +1334,12 @@ pmoderetf(int is32, uint16_t off)
if (CPL == (seg & 0x0003)) {
x86seg_log("RETF CPL = RPL %04X\n", segdat[2]);
switch (segdat[2] & 0x1f00) {
case 0x1000:
case 0x1100:
case 0x1200:
case 0x1300:
/* Data segment, apparently valid when CPL is the same, used by MS LINK for DOS. */
fallthrough;
case 0x1800:
case 0x1900:
case 0x1a00:
@@ -1384,6 +1390,12 @@ pmoderetf(int is32, uint16_t off)
cycles -= timing_retf_pm;
} else {
switch (segdat[2] & 0x1f00) {
case 0x1000:
case 0x1100:
case 0x1200:
case 0x1300:
/* Data segment, apparently valid when CPL is the same, used by MS LINK for DOS. */
fallthrough;
case 0x1800:
case 0x1900:
case 0x1a00:
@@ -1605,6 +1617,12 @@ pmodeint(int num, int soft)
return;
}
switch (segdat2[2] & 0x1f00) {
case 0x1000:
case 0x1100:
case 0x1200:
case 0x1300:
/* Data segment, apparently valid when CPL is the same, used by MS CodeView for DOS. */
fallthrough;
case 0x1800:
case 0x1900:
case 0x1a00:
@@ -1678,10 +1696,17 @@ pmodeint(int num, int soft)
cpl_override = 1;
if (type >= 0x0800) {
if (cpu_state.eflags & VM_FLAG) {
PUSHL_SEL(GS);
PUSHL_SEL(FS);
PUSHL_SEL(DS);
PUSHL_SEL(ES);
if (is586) {
PUSHL(GS);
PUSHL(FS);
PUSHL(DS);
PUSHL(ES);
} else {
PUSHL_SEL(GS);
PUSHL_SEL(FS);
PUSHL_SEL(DS);
PUSHL_SEL(ES);
}
if (cpu_state.abrt)
return;
op_loadseg(0, &cpu_state.seg_ds);
@@ -1689,10 +1714,10 @@ pmodeint(int num, int soft)
op_loadseg(0, &cpu_state.seg_fs);
op_loadseg(0, &cpu_state.seg_gs);
}
PUSHL_SEL(oldss);
is586 ? PUSHL(oldss) : PUSHL_SEL(oldss);
PUSHL(oldsp);
PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
PUSHL_SEL(CS);
is586 ? PUSHL(CS) : PUSHL_SEL(CS);
PUSHL(cpu_state.pc);
if (cpu_state.abrt)
return;
@@ -1728,7 +1753,7 @@ pmodeint(int num, int soft)
}
if (type > 0x0800) {
PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
PUSHL_SEL(CS);
is586 ? PUSHL(CS) : PUSHL_SEL(CS);
PUSHL(cpu_state.pc);
if (cpu_state.abrt)
return;
@@ -1976,6 +2001,12 @@ pmodeiret(int is32)
}
switch (segdat[2] & 0x1f00) {
case 0x1000:
case 0x1100:
case 0x1200:
case 0x1300:
/* Data segment, apparently valid when CPL is the same, used by MS CodeView for DOS. */
fallthrough;
case 0x1800:
case 0x1900:
case 0x1a00:
@@ -2574,19 +2605,17 @@ cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg)
cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
#ifdef USE_DYNAREC
codegen_flat_ds = 0;
#endif
}
if (seg == &cpu_state.seg_cs)
set_use32(segdat[3] & 0x40);
if (seg == &cpu_state.seg_ss) {
if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
set_stack32((segdat[3] & 0x40) ? 1 : 0);
#ifdef USE_DYNAREC
codegen_flat_ss = 0;
#endif
}
}
}

View File

@@ -36,6 +36,8 @@ extern void fpu_log(const char *fmt, ...);
# endif
#endif
extern double exp_pow_table[0x800];
static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO };
#define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)]
@@ -420,11 +422,19 @@ x87_compare(double a, double b)
* situations, eg comparison of infinity (Unreal) */
uint32_t result = 0;
double ea = a, eb = b;
const uint64_t ia = 0x3fec1a6ff866a936ULL;
const uint64_t ib = 0x3fec1a6ff866a938ULL;
/* Hack to make CHKCOP happy. */
if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8))
return FPU_SW_C3;
if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY)))
eb = ea;
if (ea == eb)
if ((isnan(a) || isnan(b)))
result |= FPU_SW_C3 | FPU_SW_C2 | FPU_SW_C0;
else if (ea == eb)
result |= FPU_SW_C3;
else if (ea < eb)
result |= FPU_SW_C0;
@@ -473,7 +483,9 @@ x87_ucompare(double a, double b)
* situations, eg comparison of infinity (Unreal) */
uint32_t result = 0;
if (a == b)
if ((isnan(a) || isnan(b)))
result |= FPU_SW_C3 | FPU_SW_C2 | FPU_SW_C0;
else if (a == b)
result |= FPU_SW_C3;
else if (a < b)
result |= FPU_SW_C0;

View File

@@ -46,7 +46,7 @@ opFXTRACT(UNUSED(uint32_t fetchdat))
test.eind.d = ST(0);
exp80 = test.eind.ll & 0x7ff0000000000000LL;
exp80final = (exp80 >> 52) - BIAS64;
mant = test.eind.d / (pow(2.0, (double) exp80final));
mant = test.eind.d / exp_pow_table[exp80 >> 52];
ST(0) = (double) exp80final;
FP_TAG_VALID;
x87_push(mant);
@@ -585,10 +585,24 @@ opFXAM(UNUSED(uint32_t fetchdat))
if (cpu_state.tag[cpu_state.TOP & 7] == 3)
cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3);
#endif
else if (ST(0) == 0.0)
cpu_state.npxs |= FPU_SW_C3;
else
cpu_state.npxs |= FPU_SW_C2;
else switch (fpclassify(ST(0)))
{
case FP_SUBNORMAL:
cpu_state.npxs |= FPU_SW_C2 | FPU_SW_C3;
break;
case FP_NAN:
cpu_state.npxs |= FPU_SW_C0;
break;
case FP_INFINITE:
cpu_state.npxs |= FPU_SW_C0 | FPU_SW_C2;
break;
case FP_ZERO:
cpu_state.npxs |= FPU_SW_C3;
break;
case FP_NORMAL:
cpu_state.npxs |= FPU_SW_C2;
break;
}
if (ST(0) < 0.0)
cpu_state.npxs |= FPU_SW_C1;
CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi));

View File

@@ -390,22 +390,21 @@ device_get_priv(const device_t *dev)
int
device_available(const device_t *dev)
{
const device_config_t *config = NULL;
const device_config_bios_t *bios = NULL;
if (dev != NULL) {
config = dev->config;
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
int roms_present = 0;
bios = (const device_config_bios_t *) config->bios;
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
/* Go through the ROM's in the device configuration. */
while (bios->files_no != 0) {
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
int i = 0;
for (int bf = 0; bf < bios->files_no; bf++)
for (uint8_t bf = 0; bf < bios->files_no; bf++)
i += !!rom_present(bios->files[bf]);
if (i == bios->files_no)
roms_present++;
@@ -429,21 +428,128 @@ device_available(const device_t *dev)
return 0;
}
const char *
device_get_bios_file(const device_t *dev, const char *internal_name, int file_no)
uint8_t
device_get_bios_type(const device_t *dev, const char *internal_name)
{
const device_config_t *config = NULL;
const device_config_bios_t *bios = NULL;
if (dev != NULL) {
config = dev->config;
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
bios = config->bios;
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
if (!strcmp(internal_name, bios->internal_name))
return bios->bios_type;
bios++;
}
}
config++;
}
}
}
return 0;
}
uint8_t
device_get_bios_num_files(const device_t *dev, const char *internal_name)
{
if (dev != NULL) {
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
if (!strcmp(internal_name, bios->internal_name))
return bios->files_no;
bios++;
}
}
config++;
}
}
}
return 0;
}
uint32_t
device_get_bios_local(const device_t *dev, const char *internal_name)
{
if (dev != NULL) {
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
printf("Internal name was: %s", internal_name);
if (!strcmp(internal_name, bios->internal_name))
return bios->local;
bios++;
}
}
config++;
}
}
}
return 0;
}
uint32_t
device_get_bios_file_size(const device_t *dev, const char *internal_name)
{
if (dev != NULL) {
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
/* Go through the ROM's in the device configuration. */
while (bios->files_no != 0) {
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
if (!strcmp(internal_name, bios->internal_name))
return bios->size;
bios++;
}
}
config++;
}
}
}
return 0;
}
const char *
device_get_bios_file(const device_t *dev, const char *internal_name, int file_no)
{
if (dev != NULL) {
const device_config_t *config = dev->config;
if (config != NULL) {
while (config->type != CONFIG_END) {
if (config->type == CONFIG_BIOS) {
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
/* Go through the ROM's in the device configuration. */
while ((bios != NULL) &&
(bios->name != NULL) &&
(bios->internal_name != NULL) &&
(bios->files_no != 0)) {
if (!strcmp(internal_name, bios->internal_name)) {
if (file_no < bios->files_no)
return bios->files[file_no];
@@ -660,13 +766,15 @@ device_get_config_string(const char *str)
int
device_get_config_int(const char *str)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, cfg->default_int));
cfg++;
cfg++;
}
}
return 0;
@@ -675,13 +783,15 @@ device_get_config_int(const char *str)
int
device_get_config_int_ex(const char *str, int def)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, def));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) device_current.name, (char *) str, def));
cfg++;
cfg++;
}
}
return def;
@@ -690,13 +800,15 @@ device_get_config_int_ex(const char *str, int def)
int
device_get_config_hex16(const char *str)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_hex16((char *) device_current.name, (char *) str, cfg->default_int));
cfg++;
cfg++;
}
}
return 0;
@@ -705,13 +817,15 @@ device_get_config_hex16(const char *str)
int
device_get_config_hex20(const char *str)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_hex20((char *) device_current.name, (char *) str, cfg->default_int));
cfg++;
cfg++;
}
}
return 0;
@@ -720,13 +834,15 @@ device_get_config_hex20(const char *str)
int
device_get_config_mac(const char *str, int def)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_mac((char *) device_current.name, (char *) str, def));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_mac((char *) device_current.name, (char *) str, def));
cfg++;
cfg++;
}
}
return def;
@@ -735,60 +851,68 @@ device_get_config_mac(const char *str, int def)
void
device_set_config_int(const char *str, int val)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_int((char *) device_current.name, (char *) str, val);
break;
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name)) {
config_set_int((char *) device_current.name, (char *) str, val);
break;
}
cfg++;
}
cfg++;
}
}
void
device_set_config_hex16(const char *str, int val)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_hex16((char *) device_current.name, (char *) str, val);
break;
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name)) {
config_set_hex16((char *) device_current.name, (char *) str, val);
break;
}
cfg++;
}
cfg++;
}
}
void
device_set_config_hex20(const char *str, int val)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_hex20((char *) device_current.name, (char *) str, val);
break;
}
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name)) {
config_set_hex20((char *) device_current.name, (char *) str, val);
break;
}
cfg++;
}
}
}
void
device_set_config_mac(const char *str, int val)
{
const device_config_t *cfg = device_current.dev->config;
if (device_current.dev != NULL) {
const device_config_t *cfg = device_current.dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name)) {
config_set_mac((char *) device_current.name, (char *) str, val);
break;
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name)) {
config_set_mac((char *) device_current.name, (char *) str, val);
break;
}
cfg++;
}
cfg++;
}
}
@@ -806,20 +930,18 @@ device_is_valid(const device_t *device, int mch)
int
machine_get_config_int(char *str)
{
const device_t *dev = machine_get_device(machine);
const device_config_t *cfg;
const device_t *dev = machine_get_device(machine);
if (dev == NULL)
return 0;
if (dev != NULL) {
const device_config_t *cfg = dev->config;
cfg = dev->config;
while (cfg && cfg->type != CONFIG_END) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) dev->name, str, cfg->default_int));
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name))
return (config_get_int((char *) dev->name, str, cfg->default_int));
cfg++;
cfg++;
}
}
return 0;
}
@@ -830,9 +952,8 @@ machine_get_config_string(char *str)
const char *ret = "";
if (dev != NULL) {
const device_config_t *cfg;
const device_config_t *cfg = dev->config;
cfg = dev->config;
while ((cfg != NULL) && (cfg->type != CONFIG_END)) {
if (!strcmp(str, cfg->name)) {
const char *s = config_get_string((char *) dev->name, str,

View File

@@ -1577,21 +1577,35 @@ write64_phoenix(void *priv, uint8_t val)
revision level and proper CPU bits. */
case 0xd5: /* Read MultiKey code revision level */
kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n");
kbc_at_queue_add(dev, 0x04);
kbc_at_queue_add(dev, 0x16);
if (dev->misc_flags & FLAG_PS2) {
kbc_at_queue_add(dev, 0x04);
kbc_at_queue_add(dev, 0x16);
} else {
kbc_at_queue_add(dev, 0x01);
kbc_at_queue_add(dev, 0x29);
}
return 0;
case 0xd6: /* Read Version Information */
kbc_at_log("ATkbc: Phoenix - Read Version Information\n");
kbc_at_queue_add(dev, 0x81);
kbc_at_queue_add(dev, 0xac);
if (dev->misc_flags & FLAG_PS2)
kbc_at_queue_add(dev, 0xac);
else
kbc_at_queue_add(dev, 0xaa);
return 0;
case 0xd7: /* Read MultiKey model numbers */
kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n");
kbc_at_queue_add(dev, 0x02);
kbc_at_queue_add(dev, 0x87);
kbc_at_queue_add(dev, 0x02);
if (dev->misc_flags & FLAG_PS2) {
kbc_at_queue_add(dev, 0x02);
kbc_at_queue_add(dev, 0x87);
kbc_at_queue_add(dev, 0x02);
} else {
kbc_at_queue_add(dev, 0x90);
kbc_at_queue_add(dev, 0x88);
kbc_at_queue_add(dev, 0xd0);
}
return 0;
default:
@@ -2510,6 +2524,20 @@ const device_t keyboard_at_compaq_device = {
.config = NULL
};
const device_t keyboard_at_phoenix_device = {
.name = "PC/AT Keyboard (Phoenix)",
.internal_name = "keyboard_at_phoenix",
.flags = DEVICE_KBC,
.local = KBC_TYPE_ISA | KBC_VEN_PHOENIX,
.init = kbc_at_init,
.close = kbc_at_close,
.reset = kbc_at_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t keyboard_ps2_device = {
.name = "PS/2 Keyboard",
.internal_name = "keyboard_ps2",

View File

@@ -84,6 +84,7 @@ typedef struct xtkbd_t {
uint8_t key_waiting;
uint8_t type;
uint8_t pravetz_flags;
uint8_t cpu_speed;
pc_timer_t send_delay_timer;
} xtkbd_t;
@@ -799,6 +800,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
kbd_adddata(0xaa);
}
}
kbd->pb = val;
if (!(kbd->pb & 0x80) || (kbd->type == KBD_TYPE_HYUNDAI))
kbd->clock = !!(kbd->pb & 0x40);
@@ -846,6 +848,14 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
}
break;
case 0x1f0:
kbd_log("XTkbd: Port %04X out: %02X\n", port, val);
if (kbd->type == KBD_TYPE_VTECH) {
kbd->cpu_speed = val;
cpu_dynamic_switch(kbd->cpu_speed >> 7);
}
break;
default:
break;
}
@@ -863,12 +873,14 @@ kbd_read(uint16_t port, void *priv)
(kbd->type == KBD_TYPE_PC82) || (kbd->type == KBD_TYPE_PRAVETZ) ||
(kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI))) {
(kbd->type == KBD_TYPE_ZENITH) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))) {
if ((kbd->type == KBD_TYPE_PC81) || (kbd->type == KBD_TYPE_PC82) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_HYUNDAI))
ret = (kbd->pd & ~0x02) | (hasfpu ? 0x02 : 0x00);
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86))
else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_VTECH))
/* According to Ruud on the PCem forum, this is supposed to
return 0xFF on the XT. */
ret = 0xff;
@@ -926,16 +938,8 @@ kbd_read(uint16_t port, void *priv)
} else {
if (kbd->pb & 0x08) /* PB3 */
ret = kbd->pd >> 4;
else {
/* LaserXT = Always 512k RAM;
LaserXT/3 = Bit 0: set = 512k, clear = 256k. */
#ifdef USE_LASERXT
if (kbd->type == KBD_TYPE_VTECH)
ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00);
else
#endif /* USE_LASERXT */
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
}
else
ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00);
}
ret |= (ppispeakon ? 0x20 : 0);
@@ -956,7 +960,8 @@ kbd_read(uint16_t port, void *priv)
case 0x63: /* Keyboard Configuration Register (aka Port D) */
if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_XT86) ||
(kbd->type == KBD_TYPE_XTCLONE) || (kbd->type == KBD_TYPE_COMPAQ) ||
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI))
(kbd->type == KBD_TYPE_TOSHIBA) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH))
ret = kbd->pd;
break;
@@ -966,6 +971,12 @@ kbd_read(uint16_t port, void *priv)
kbd_log("XTkbd: Port %02X in : %02X\n", port, ret);
break;
case 0x1f0:
if (kbd->type == KBD_TYPE_VTECH)
ret = kbd->cpu_speed;
kbd_log("XTkbd: Port %04X in : %02X\n", port, ret);
break;
default:
break;
}
@@ -984,7 +995,7 @@ kbd_reset(void *priv)
kbd->pb = 0x00;
kbd->pravetz_flags = 0x00;
keyboard_scan = 1;
keyboard_scan = 1;
key_queue_start = 0;
key_queue_end = 0;
@@ -1006,12 +1017,16 @@ kbd_init(const device_t *info)
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;
if (kbd->type == KBD_TYPE_PRAVETZ) {
if (kbd->type == KBD_TYPE_VTECH)
kbd->cpu_speed = (!!cpu) << 2;
kbd_reset(kbd);
if (kbd->type == KBD_TYPE_PRAVETZ)
io_sethandler(0x00c0, 16,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
}
if (kbd->type == KBD_TYPE_VTECH)
io_sethandler(0x01f0, 1,
kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd);
key_queue_start = key_queue_end = 0;
@@ -1021,7 +1036,8 @@ kbd_init(const device_t *info)
(kbd->type == KBD_TYPE_PRAVETZ) || (kbd->type == KBD_TYPE_XT82) ||
(kbd->type <= KBD_TYPE_XT86) || (kbd->type == KBD_TYPE_XTCLONE) ||
(kbd->type == KBD_TYPE_COMPAQ) || (kbd->type == KBD_TYPE_TOSHIBA) ||
(kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI)) {
(kbd->type == KBD_TYPE_OLIVETTI) || (kbd->type == KBD_TYPE_HYUNDAI) ||
(kbd->type == KBD_TYPE_VTECH)) {
/* DIP switch readout: bit set = OFF, clear = ON. */
if (kbd->type == KBD_TYPE_OLIVETTI)
/* Olivetti M19
@@ -1035,7 +1051,7 @@ kbd_init(const device_t *info)
/* Switches 7, 8 - floppy drives. */
kbd->pd = get_fdd_switch_settings();
/* Siitches 5, 6 - video card type */
/* Switches 5, 6 - video card type */
kbd->pd |= get_videomode_switch_settings();
/* Switches 3, 4 - memory size. */
@@ -1057,7 +1073,7 @@ kbd_init(const device_t *info)
kbd->pd |= 0x0c;
break;
}
} else if (kbd->type == KBD_TYPE_XT82) {
} else if ((kbd->type == KBD_TYPE_XT82) || (kbd->type == KBD_TYPE_VTECH)) {
switch (mem_size) {
case 64: /* 1x64k */
kbd->pd |= 0x00;
@@ -1075,9 +1091,13 @@ kbd_init(const device_t *info)
}
} else if (kbd->type == KBD_TYPE_PC82) {
switch (mem_size) {
#ifdef PC82_192K_3BANK
case 192: /* 3x64k, not supported by stock BIOS due to bugs */
kbd->pd |= 0x08;
break;
#else
case 192: /* 2x64k + 2x32k */
#endif
case 64: /* 4x16k */
case 96: /* 2x32k + 2x16k */
case 128: /* 4x32k */
@@ -1294,8 +1314,8 @@ const device_t keyboard_xt_t1x00_device = {
#ifdef USE_LASERXT
const device_t keyboard_xt_lxt3_device = {
.name = "VTech Laser XT3 Keyboard",
.internal_name = "keyboard_xt_lxt3",
.name = "VTech Laser Turbo XT Keyboard",
.internal_name = "keyboard_xt_lxt",
.flags = 0,
.local = KBD_TYPE_VTECH,
.init = kbd_init,

View File

@@ -106,6 +106,7 @@ static mouse_t mouse_devices[] = {
static _Atomic double mouse_x;
static _Atomic double mouse_y;
static atomic_int mouse_z;
static atomic_int mouse_w;
static atomic_int mouse_buttons;
static int mouse_delta_b;
@@ -156,6 +157,7 @@ mouse_clear_coords(void)
mouse_clear_y();
mouse_z = 0;
mouse_w = 0;
}
void
@@ -355,6 +357,14 @@ mouse_wheel_moved(void)
return ret;
}
int
mouse_hwheel_moved(void)
{
int ret = !!(atomic_load(&mouse_w));
return ret;
}
int
mouse_moved(void)
{
@@ -373,13 +383,14 @@ mouse_state_changed(void)
int b;
int b_mask = (1 << mouse_nbut) - 1;
int wheel = (mouse_nbut >= 4);
int hwheel = (mouse_nbut >= 6);
int ret;
b = atomic_load(&mouse_buttons);
mouse_delta_b = (b ^ mouse_old_b);
mouse_old_b = b;
ret = mouse_moved() || ((atomic_load(&mouse_z) != 0) && wheel) || (mouse_delta_b & b_mask);
ret = mouse_moved() || ((atomic_load(&mouse_z) != 0) && wheel) || ((atomic_load(&mouse_w) != 0) && hwheel) || (mouse_delta_b & b_mask);
return ret;
}
@@ -475,6 +486,18 @@ mouse_clear_z(void)
atomic_store(&mouse_z, 0);
}
void
mouse_set_w(int w)
{
atomic_fetch_add(&mouse_w, w);
}
void
mouse_clear_w(void)
{
atomic_store(&mouse_w, 0);
}
void
mouse_subtract_z(int *delta_z, int min, int max, int invert)
{
@@ -495,6 +518,26 @@ mouse_subtract_z(int *delta_z, int min, int max, int invert)
atomic_store(&mouse_z, invert ? -real_z : real_z);
}
void
mouse_subtract_w(int *delta_w, int min, int max, int invert)
{
int w = atomic_load(&mouse_w);
int real_w = invert ? -w : w;
if (real_w > max) {
*delta_w = max;
real_w -= max;
} else if (real_w < min) {
*delta_w = min;
real_w += ABS(min);
} else {
*delta_w = real_w;
real_w = 0;
}
atomic_store(&mouse_w, invert ? -real_w : real_w);
}
void
mouse_set_buttons_ex(int b)
{

View File

@@ -34,13 +34,15 @@ enum {
MODE_ECHO
};
#define FLAG_EXPLORER 0x200 /* Has 5 buttons */
#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */
#define FLAG_INTELLI 0x80 /* device is IntelliMouse */
#define FLAG_INTMODE 0x40 /* using Intellimouse mode */
#define FLAG_SCALED 0x20 /* enable delta scaling */
#define FLAG_ENABLED 0x10 /* dev is enabled for use */
#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */
#define FLAG_HWHL 0x800 /* Report horizontal wheel movements. */
#define FLAG_EXPLORER_HWHL 0x400 /* Has tilt-wheel/horizontal scroll wheel */
#define FLAG_EXPLORER 0x200 /* Has 5 buttons */
#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */
#define FLAG_INTELLI 0x80 /* device is IntelliMouse */
#define FLAG_INTMODE 0x40 /* using Intellimouse mode */
#define FLAG_SCALED 0x20 /* enable delta scaling */
#define FLAG_ENABLED 0x10 /* dev is enabled for use */
#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */
#define FIFO_SIZE 16
@@ -82,10 +84,16 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
int overflow_y;
int b = mouse_get_buttons_ex();
int delta_z;
int delta_w;
mouse_subtract_coords(&delta_x, &delta_y, &overflow_x, &overflow_y,
-256, 255, 1, 0);
mouse_subtract_z(&delta_z, -8, 7, 1);
if (dev->flags & FLAG_5BTN)
mouse_subtract_z(&delta_z, -32, 31, 1);
else
mouse_subtract_z(&delta_z, -8, 7, 1);
mouse_subtract_w(&delta_w, -1, 1, 0);
buff[0] |= (overflow_y << 7) | (overflow_x << 6) |
((delta_y & 0x0100) >> 3) | ((delta_x & 0x0100) >> 4) |
@@ -97,10 +105,21 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
kbc_at_dev_queue_add(dev, buff[1], main);
kbc_at_dev_queue_add(dev, buff[2], main);
if (dev->flags & FLAG_INTMODE) {
delta_z &= 0x0f;
delta_z &= (dev->flags & FLAG_HWHL) ? 0x3f : 0x0f;
if (dev->flags & FLAG_5BTN) {
if (b & 8)
if ((dev->flags & FLAG_HWHL) && (delta_z || delta_w))
{
if (delta_w) {
delta_z = delta_w;
delta_z &= 0x3f;
delta_z |= 0x40;
} else {
delta_z &= 0x3f;
delta_z |= 0x80;
}
}
else if (b & 8)
delta_z |= 0x10;
if (b & 16)
delta_z |= 0x20;
@@ -120,7 +139,7 @@ ps2_set_defaults(atkbc_dev_t *dev)
dev->rate = 100;
mouse_set_sample_rate(100.0);
dev->resolution = 2;
dev->flags &= 0x188;
dev->flags &= 0x688;
mouse_scan = 0;
}
@@ -298,6 +317,13 @@ ps2_write(void *priv)
(last_data[2] == 0xf3) && (last_data[3] == 0xc8) &&
(last_data[4] == 0xf3) && (last_data[5] == 0x50))
dev->flags |= FLAG_5BTN;
if ((dev->flags & FLAG_5BTN) && (dev->flags & FLAG_EXPLORER_HWHL) &&
(last_data[0] == 0xf3) && (last_data[1] == 0xc8) &&
(last_data[2] == 0xf3) && (last_data[3] == 0x50) &&
(last_data[4] == 0xf3) && (last_data[5] == 0x28))
dev->flags |= FLAG_HWHL;
}
}
@@ -336,6 +362,8 @@ mouse_ps2_init(const device_t *info)
dev->flags |= FLAG_INTELLI;
if (i > 4)
dev->flags |= FLAG_EXPLORER;
if (i > 5)
dev->flags |= FLAG_EXPLORER_HWHL;
mouse_ps2_log("%s: buttons=%d\n", dev->name, i);
@@ -377,11 +405,12 @@ static const device_config_t ps2_config[] = {
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Two", .value = 2 },
{ .description = "Three", .value = 3 },
{ .description = "Wheel", .value = 4 },
{ .description = "Five + Wheel", .value = 5 },
{ .description = "" }
{ .description = "Two", .value = 2 },
{ .description = "Three", .value = 3 },
{ .description = "Wheel", .value = 4 },
{ .description = "Five + Wheel", .value = 5 },
{ .description = "Five + 2 Wheels", .value = 6 },
{ .description = "" }
},
.bios = { { 0 } }
},

View File

@@ -72,7 +72,9 @@ static const struct {
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_2ch_device },
{ &xtide_at_ps2_device },
{ &xtide_at_ps2_2ch_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },

View File

@@ -117,7 +117,7 @@
#define ROM_PATH_MCIDE "roms/hdd/xtide/ide_ps2 R1.1.bin"
typedef struct ide_bm_t {
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv);
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv);
void (*set_irq)(uint8_t status, void *priv);
void *priv;
} ide_bm_t;
@@ -1028,9 +1028,8 @@ ide_atapi_command_bus(ide_t *ide)
static void
ide_atapi_callback(ide_t *ide)
{
int out;
int ret = 0;
ide_bm_t *bm = ide_boards[ide->board]->bm;
static int ret = 0;
ide_bm_t *bm = ide_boards[ide->board]->bm;
#ifdef ENABLE_IDE_LOG
char *phases[7] = { "Idle", "Command", "Data in", "Data out", "Data in DMA", "Data out DMA",
"Complete" };
@@ -1056,14 +1055,17 @@ ide_atapi_callback(ide_t *ide)
switch (ide->sc->packet_status) {
default:
ret = 0;
break;
case PHASE_IDLE:
ret = 0;
ide->tf->pos = 0;
ide->tf->phase = 1;
ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT);
break;
case PHASE_COMMAND:
ret = 1;
ide->tf->atastat = BUSY_STAT | (ide->tf->atastat & ERR_STAT);
if (ide->packet_command) {
ide->packet_command(ide->sc, ide->sc->atapi_cdb);
@@ -1073,6 +1075,7 @@ ide_atapi_callback(ide_t *ide)
break;
case PHASE_COMPLETE:
case PHASE_ERROR:
ret = 0;
ide->tf->atastat = READY_STAT;
if (ide->sc->packet_status == PHASE_ERROR)
ide->tf->atastat |= ERR_STAT;
@@ -1082,19 +1085,35 @@ ide_atapi_callback(ide_t *ide)
break;
case PHASE_DATA_IN:
case PHASE_DATA_OUT:
ret = 0;
ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT);
ide->tf->phase = !(ide->sc->packet_status & 0x01) << 1;
ide_irq_raise(ide);
break;
case PHASE_DATA_IN_DMA:
case PHASE_DATA_OUT_DMA:
out = (ide->sc->packet_status & 0x01);
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
(bm != NULL) && bm->dma) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, bm->priv);
}
/* Else, DMA command without a bus master, ret = 0 (default). */
if (ide->sc->block_len == 0) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 0, bm->priv);
/* Underrun. */
if (ret == 1)
ret = 3;
} else {
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos -
ide->sc->block_len, ide->sc->block_len,
ide->sc->sector_len * ide->sc->block_len,
0, bm->priv);
if (ret == 1) {
if (ide->sc->sector_len == 0)
ret = 3;
else if (ide->read != NULL)
ide->read(ide->sc);
}
}
} else
ret = 0;
switch (ret) {
default:
@@ -1103,18 +1122,75 @@ ide_atapi_callback(ide_t *ide)
if (ide->bus_master_error)
ide->bus_master_error(ide->sc);
break;
case 1:
if (out && ide->phase_data_out)
(void) ide->phase_data_out(ide->sc);
else if (!out && ide->command_stop)
ide->command_stop(ide->sc);
case 2:
ide_atapi_command_bus(ide);
break;
case 3:
/* Reached EOT - terminate the command as there's nothing
more to transfer. */
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
if (ide->command_stop != NULL)
ide->command_stop(ide->sc);
fallthrough;
case 1:
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
(ide->sc->callback == 0.0))
ide_atapi_callback(ide);
break;
}
break;
case PHASE_DATA_OUT_DMA:
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
(bm != NULL) && bm->dma) {
if (ide->sc->block_len == 0) {
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 1, bm->priv);
/* Underrun. */
if (ret == 1)
ret = 3;
} else {
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos,
ide->sc->block_len,
ide->sc->sector_len * ide->sc->block_len,
1, bm->priv);
if (ret & 1) {
if (ide->write != NULL)
ide->write(ide->sc);
if ((ret == 1) && (ide->sc->sector_len == 0))
ret = 3;
}
}
} else
ret = 0;
switch (ret) {
default:
break;
case 0:
if (ide->bus_master_error)
ide->bus_master_error(ide->sc);
break;
case 2:
ide_atapi_command_bus(ide);
break;
case 3:
/* Reached EOT - terminate the command as there's nothing
more to transfer. */
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if (ide->phase_data_out != NULL)
(void) ide->phase_data_out(ide->sc);
fallthrough;
case 1:
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
(ide->sc->callback == 0.0))
ide_atapi_callback(ide);
break;
}
break;
}
@@ -1124,32 +1200,43 @@ ide_atapi_callback(ide_t *ide)
static void
ide_atapi_pio_request(ide_t *ide, uint8_t out)
{
scsi_common_t *dev = ide->sc;
scsi_common_t *dev = ide->sc;
int left = 0;
ide_irq_lower(ide);
ide->tf->atastat = BSY_STAT;
ide->tf->atastat = BSY_STAT;
if (ide->tf->pos >= dev->packet_len) {
ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read");
ide->tf->pos = dev->request_pos = 0;
if (out && ide->phase_data_out)
ide->phase_data_out(dev);
else if (!out && ide->command_stop)
ide->command_stop(dev);
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
ide_atapi_callback(ide);
if (dev->block_len == 0) {
if (out && (ide->phase_data_out != NULL))
ide->phase_data_out(dev);
else if (!out && (ide->command_stop != NULL))
ide->command_stop(dev);
if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0))
ide_atapi_callback(ide);
}
} else {
ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos,
out ? "written" : "read", dev->packet_len - ide->tf->pos);
/* If less than (packet length) bytes are remaining, update packet length
accordingly. */
left = 1;
/*
If less than (packet length) bytes are remaining, update packet length
accordingly.
*/
if ((dev->packet_len - ide->tf->pos) < (dev->max_transfer_len)) {
dev->max_transfer_len = dev->packet_len - ide->tf->pos;
/* Also update the request length so the host knows how many bytes to transfer. */
/*
Also update the request length so the host knows how many bytes to
transfer.
*/
ide->tf->request_length = dev->max_transfer_len;
}
ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len,
@@ -1157,12 +1244,50 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
dev->packet_status = PHASE_DATA_IN | out;
ide->tf->atastat = BSY_STAT;
ide->tf->phase = 1;
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
if (dev->block_len == 0) {
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
}
dev->request_pos = 0;
dev->request_pos = 0;
}
if (dev->block_len != 0) {
if (out) {
if (ide->write != NULL)
ide->write(dev);
if (dev->sector_len == 0) {
if (left) {
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
} else {
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
if (ide->phase_data_out != NULL)
(void) ide->phase_data_out(dev);
ide_atapi_callback(ide);
}
}
} else {
if (dev->sector_len == 0) {
if (left) {
ide_atapi_callback(ide);
ide_set_callback(ide, 0.0);
} else {
if (ide->command_stop != NULL)
ide->command_stop(dev);
ide->sc->packet_status = PHASE_COMPLETE;
ide->sc->callback = 0.0;
ide_atapi_callback(ide);
}
} else if (ide->read != NULL)
ide->read(dev);
}
}
}
@@ -1179,16 +1304,19 @@ ide_atapi_packet_read(ide_t *ide)
bufferw = (uint16_t *) dev->temp_buffer;
/* Make sure we return a 0 and don't attempt to read from the buffer if
/*
Make sure we return a 0 and don't attempt to read from the buffer if
we're transferring bytes beyond it, which can happen when issuing media
access commands with an allocated length below minimum request length
(which is 1 sector = 2048 bytes). */
(which is 1 sector = 2048 bytes).
*/
ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0;
ide->tf->pos += 2;
dev->request_pos += 2;
if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) {
if ((dev->request_pos >= dev->max_transfer_len) ||
(ide->tf->pos >= dev->packet_len)) {
/* Time for a DRQ. */
ide_atapi_pio_request(ide, 0);
}
@@ -1221,7 +1349,8 @@ ide_atapi_packet_write(ide_t *ide, const uint16_t val)
dev->request_pos += 2;
if (dev->packet_status == PHASE_DATA_OUT) {
if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) {
if ((dev->request_pos >= dev->max_transfer_len) ||
(ide->tf->pos >= dev->packet_len)) {
/* Time for a DRQ. */
ide_atapi_pio_request(ide, 1);
}
@@ -1287,7 +1416,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv)
ide = ide_drives[ch];
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writew(%04X, %04X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
#endif
addr &= 0x7;
@@ -1321,7 +1450,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv)
ide = ide_drives[ch];
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writel(%04X, %08X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
#endif
addr &= 0x7;
@@ -1371,9 +1500,9 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv)
ide = ide_drives[ch];
ide_other = ide_drives[ch ^ 1];
ide_log("ide_write_devctl(%04X, %02X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_write_devctl(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
if ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE))
if ((addr & 0x0001) || ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE)))
return;
dev->diag = 0;
@@ -1481,7 +1610,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
ide = ide_drives[ch];
ide_other = ide_drives[ch ^ 1];
ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv);
ide_log("[%04X:%08X] ide_writeb(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv);
addr &= 0x7;
@@ -1831,7 +1960,7 @@ ide_read_data(ide_t *ide)
const uint16_t *idebufferw = ide->buffer;
uint16_t ret = 0x0000;
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 3)
ide_log("ide_read_data(): ch = %i, board = %i, type = %i\n", ide->channel,
ide->board, ide->type);
#endif
@@ -2010,7 +2139,7 @@ ide_readb(uint16_t addr, void *priv)
break;
}
ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readb(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
return ret;
}
@@ -2022,12 +2151,14 @@ ide_read_alt_status(UNUSED(const uint16_t addr), void *priv)
const int ch = dev->cur_dev;
ide_t * ide = ide_drives[ch];
uint8_t ret = 0xff;
/* Per the Seagate ATA-3 specification:
Reading the alternate status does *NOT* clear the IRQ. */
const uint8_t ret = ide_status(ide, ide_drives[ch ^ 1], ch);
if (!(addr & 0x0001))
ret = ide_status(ide, ide_drives[ch ^ 1], ch);
ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
return ret;
}
@@ -2053,7 +2184,7 @@ ide_readw(uint16_t addr, void *priv)
}
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readw(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret);
#endif
return ret;
}
@@ -2084,7 +2215,7 @@ ide_readl(uint16_t addr, void *priv)
}
#if defined(ENABLE_IDE_LOG) && (ENABLE_IDE_LOG == 2)
ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret);
ide_log("[%04X:%08X] ide_readl(%04X, %08X) = %04X\n", CS, cpu_state.pc, addr, priv, ret);
#endif
return ret;
}
@@ -2264,13 +2395,13 @@ ide_callback(void *priv)
err = UNC_ERR;
} else if (!ide_boards[ide->board]->force_ata3 && bm->dma) {
/* We should not abort - we should simply wait for the host to start DMA. */
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, bm->priv);
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 0, bm->priv);
if (ret == 2) {
/* Bus master DMA disabled, simply wait for the host to enable DMA. */
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
ide_set_callback(ide, 6.0 * IDE_TIME);
return;
} else if (ret == 1) {
} else if (ret & 1) {
/* DMA successful */
ide_log("IDE %i: DMA read successful\n", ide->channel);
@@ -2372,14 +2503,14 @@ ide_callback(void *priv)
else
ide->sector_pos = 256;
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 1, bm->priv);
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 1, bm->priv);
if (ret == 2) {
/* Bus master DMA disabled, simply wait for the host to enable DMA. */
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
ide_set_callback(ide, 6.0 * IDE_TIME);
return;
} else if (ret == 1) {
} else if (ret & 1) {
/* DMA successful */
ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide),
ide->sector_pos, ide->sector_buffer);
@@ -2637,7 +2768,7 @@ ide_handlers(uint8_t board, int set)
}
if (ide_boards[board]->base[1]) {
io_handler(set, ide_boards[board]->base[1], 1,
io_handler(set, ide_boards[board]->base[1], 2,
ide_read_alt_status, NULL, NULL,
ide_write_devctl, NULL, NULL,
ide_boards[board]);
@@ -2999,7 +3130,7 @@ ide_xtide_close(void)
void
ide_set_bus_master(int board,
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv),
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv),
void (*set_irq)(uint8_t status, void *priv), void *priv)
{
ide_bm_t *bm;

View File

@@ -95,19 +95,19 @@ cmd646_set_irq_1(uint8_t status, void *priv)
}
static int
cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int out, void *priv)
cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
{
const cmd646_t *dev = (cmd646_t *) priv;
return sff_bus_master_dma(data, transfer_length, out, dev->bm[0]);
return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[0]);
}
static int
cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int out, void *priv)
cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
{
const cmd646_t *dev = (cmd646_t *) priv;
return sff_bus_master_dma(data, transfer_length, out, dev->bm[1]);
return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[1]);
}
static void

View File

@@ -316,14 +316,14 @@ sff_bus_master_readl(uint16_t port, void *priv)
}
int
sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
{
sff8038i_t *dev = (sff8038i_t *) priv;
#ifdef ENABLE_SFF_LOG
char *sop;
#endif
int force_end = 0;
int force_end = 0;
int buffer_pos = 0;
#ifdef ENABLE_SFF_LOG
@@ -365,9 +365,15 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
} else {
if (!transfer_length && !dev->eot) {
sff_log("Total transfer length smaller than sum of all blocks, full block\n");
dev->status &= ~2;
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
if (total_length) {
sff_log("Total transfer length smaller than sum of all blocks, partial transfer\n");
sff_bus_master_next_addr(dev);
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
} else {
sff_log("Total transfer length smaller than sum of all blocks, full block\n");
dev->status &= ~2;
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
}
} else if (transfer_length && dev->eot) {
sff_log("Total transfer length greater than sum of all blocks\n");
dev->status |= 2;
@@ -375,7 +381,7 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
} else if (dev->eot) {
sff_log("Regular EOT\n");
dev->status &= ~3;
return 1; /* We have regularly reached EOT - clear status and break. */
return 3; /* We have regularly reached EOT - clear status and break. */
} else {
/* We have more to transfer and there are blocks left, get next block. */
sff_bus_master_next_addr(dev);

View File

@@ -41,11 +41,13 @@
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/device.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/plat_unused.h>
#define ROM_PATH_TINY "roms/hdd/xtide/ide_tiny.bin"
#define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin"
#define ROM_PATH_XTP "roms/hdd/xtide/ide_xtp.bin"
#define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin"
@@ -57,6 +59,7 @@ typedef struct xtide_t {
void *ide_board;
uint8_t data_high;
rom_t bios_rom;
char nvr_path[64];
} xtide_t;
static void
@@ -136,14 +139,26 @@ xtide_init(const device_t *info)
rom_init(&xtide->bios_rom,
device_get_bios_file(info, device_get_config_bios("bios"), 0),
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
device_get_config_hex20("bios_addr"), 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
xtide->ide_board = ide_xtide_init();
io_sethandler(0x0300, 16,
io_sethandler(device_get_config_hex16("base"), 16,
xtide_read, NULL, NULL,
xtide_write, NULL, NULL, xtide);
uint8_t rom_writes_enabled = device_get_config_int("rom_writes_enabled");
if (rom_writes_enabled) {
mem_mapping_set_write_handler(&xtide->bios_rom.mapping, rom_write, rom_writew, rom_writel);
sprintf(xtide->nvr_path, "xtide_%i.nvr", device_get_instance());
FILE *fp = nvr_fopen(xtide->nvr_path, "rb");
if (fp != NULL) {
fread(xtide->bios_rom.rom, 1, 0x2000, fp);
fclose(fp);
}
}
return xtide;
}
@@ -156,7 +171,10 @@ xtide_at_init(const device_t *info)
device_get_bios_file(info, device_get_config_bios("bios"), 0),
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
device_add(&ide_isa_2ch_device);
if (info->local == 1)
device_add(&ide_isa_2ch_device);
else
device_add(&ide_isa_device);
return xtide;
}
@@ -189,6 +207,14 @@ xtide_close(void *priv)
{
xtide_t *xtide = (xtide_t *) priv;
if (xtide->nvr_path[0] != 0x00) {
FILE *fp = nvr_fopen(xtide->nvr_path, "wb");
if (fp != NULL) {
fwrite(xtide->bios_rom.rom, 1, 0x2000, fp);
fclose(fp);
}
}
free(xtide);
ide_xtide_close();
@@ -202,7 +228,10 @@ xtide_at_ps2_init(UNUSED(const device_t *info))
rom_init(&xtide->bios_rom, ROM_PATH_PS2AT,
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
device_add(&ide_isa_2ch_device);
if (info->local == 1)
device_add(&ide_isa_2ch_device);
else
device_add(&ide_isa_device);
return xtide;
}
@@ -221,8 +250,104 @@ xtide_at_close(void *priv)
free(xtide);
}
// clang-format off
static const device_config_t xtide_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0x300,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "200H", .value = 0x200 },
{ .description = "210H", .value = 0x210 },
{ .description = "220H", .value = 0x220 },
{ .description = "230H", .value = 0x230 },
{ .description = "240H", .value = 0x240 },
{ .description = "250H", .value = 0x250 },
{ .description = "260H", .value = 0x260 },
{ .description = "270H", .value = 0x270 },
{ .description = "280H", .value = 0x280 },
{ .description = "290H", .value = 0x290 },
{ .description = "2A0H", .value = 0x2a0 },
{ .description = "2B0H", .value = 0x2b0 },
{ .description = "2C0H", .value = 0x2c0 },
{ .description = "2D0H", .value = 0x2d0 },
{ .description = "2E0H", .value = 0x2e0 },
{ .description = "2F0H", .value = 0x2f0 },
{ .description = "300H", .value = 0x300 },
{ .description = "310H", .value = 0x310 },
{ .description = "320H", .value = 0x320 },
{ .description = "330H", .value = 0x330 },
{ .description = "340H", .value = 0x340 },
{ .description = "350H", .value = 0x350 },
{ .description = "360H", .value = 0x360 },
{ .description = "370H", .value = 0x370 },
{ .description = "380H", .value = 0x380 },
{ .description = "390H", .value = 0x390 },
{ .description = "3A0H", .value = 0x3a0 },
{ .description = "3B0H", .value = 0x3b0 },
{ .description = "3C0H", .value = 0x3c0 },
{ .description = "3D0H", .value = 0x3d0 },
{ .description = "3E0H", .value = 0x3e0 },
{ .description = "3F0H", .value = 0x3f0 },
{ NULL }
},
.bios = { { 0 } }
},
{
.name = "rom_writes_enabled",
.description = "Enable BIOS extension ROM Writes",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "bios_addr",
.description = "BIOS Address",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0xd0000,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0x00000 },
#if 0
// Supported on XT IDE Deluxe By Monotech
{ .description = "C000H", .value = 0xc0000 },
{ .description = "C200H", .value = 0xc2000 },
{ .description = "C400H", .value = 0xc4000 },
{ .description = "C600H", .value = 0xc6000 },
#endif
{ .description = "C800H", .value = 0xc8000 },
{ .description = "CA00H", .value = 0xca000 },
{ .description = "CC00H", .value = 0xcc000 },
{ .description = "CE00H", .value = 0xce000 },
{ .description = "D000H", .value = 0xd0000 },
{ .description = "D200H", .value = 0xd2000 },
{ .description = "D400H", .value = 0xd4000 },
{ .description = "D600H", .value = 0xd6000 },
{ .description = "D800H", .value = 0xd8000 },
{ .description = "DA00H", .value = 0xda000 },
{ .description = "DC00H", .value = 0xdc000 },
{ .description = "DE00H", .value = 0xde000 },
#if 0
// Supported on VCFed rev 2
{ .description = "E000H", .value = 0xe0000 },
{ .description = "E400H", .value = 0xe4000 },
{ .description = "E800H", .value = 0xe8000 },
{ .description = "EC00H", .value = 0xec000 },
#endif
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "bios",
.description = "BIOS Revision",
@@ -255,11 +380,9 @@ static const device_config_t xtide_config[] = {
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_config_t xtide_at_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Revision",
@@ -292,8 +415,8 @@ static const device_config_t xtide_at_config[] = {
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
// clang-format on
const device_t xtide_device = {
.name = "PC/XT XTIDE",
@@ -310,10 +433,24 @@ const device_t xtide_device = {
};
const device_t xtide_at_device = {
.name = "PC/AT XTIDE (Primary Only)",
.internal_name = "xtide_at_1ch",
.flags = DEVICE_ISA16,
.local = 0,
.init = xtide_at_init,
.close = xtide_at_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = xtide_at_config
};
const device_t xtide_at_2ch_device = {
.name = "PC/AT XTIDE",
.internal_name = "xtide_at",
.flags = DEVICE_ISA16,
.local = 0,
.local = 1,
.init = xtide_at_init,
.close = xtide_at_close,
.reset = NULL,
@@ -338,8 +475,8 @@ const device_t xtide_acculogic_device = {
};
const device_t xtide_at_ps2_device = {
.name = "PS/2 AT XTIDE (1.1.5)",
.internal_name = "xtide_at_ps2",
.name = "PS/2 AT XTIDE (1.1.5) (Primary Only)",
.internal_name = "xtide_at_ps2_1ch",
.flags = DEVICE_ISA16,
.local = 0,
.init = xtide_at_ps2_init,
@@ -350,3 +487,17 @@ const device_t xtide_at_ps2_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t xtide_at_ps2_2ch_device = {
.name = "PS/2 AT XTIDE (1.1.5)",
.internal_name = "xtide_at_ps2",
.flags = DEVICE_ISA16,
.local = 1,
.init = xtide_at_ps2_init,
.close = xtide_at_close,
.reset = NULL,
.available = xtide_at_ps2_available,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -17,6 +17,8 @@
* Copyright 2020-2025 Miran Grca.
* Copyright 2020-2025 Fred N. van Kempen
*/
#define _GNU_SOURCE
#include <inttypes.h>
#ifdef ENABLE_MO_LOG
#include <stdarg.h>
#endif
@@ -63,7 +65,7 @@ const uint8_t mo_command_flags[0x100] = {
[0x0a] = IMPLEMENTED | CHECK_READY,
[0x0b] = IMPLEMENTED | CHECK_READY,
[0x12] = IMPLEMENTED | ALLOW_UA,
[0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY,
[0x13] = IMPLEMENTED | CHECK_READY,
[0x15] = IMPLEMENTED,
[0x16] = IMPLEMENTED | SCSI_ONLY,
[0x17] = IMPLEMENTED | SCSI_ONLY,
@@ -74,8 +76,7 @@ const uint8_t mo_command_flags[0x100] = {
[0x25] = IMPLEMENTED | CHECK_READY,
[0x28] = IMPLEMENTED | CHECK_READY,
[0x2a ... 0x2c] = IMPLEMENTED | CHECK_READY,
[0x2e] = IMPLEMENTED | CHECK_READY,
[0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY,
[0x2e ... 0x2f] = IMPLEMENTED | CHECK_READY,
[0x41] = IMPLEMENTED | CHECK_READY,
[0x55] = IMPLEMENTED,
[0x5a] = IMPLEMENTED,
@@ -172,9 +173,9 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert)
}
if (ret) {
fseek(dev->drv->fp, 0, SEEK_END);
fseeko64(dev->drv->fp, 0, SEEK_END);
uint32_t size = (uint32_t) ftell(dev->drv->fp);
uint64_t size = (uint64_t) ftello64(dev->drv->fp);
unsigned int found = 0;
if (is_mdi) {
@@ -184,17 +185,20 @@ mo_load(const mo_t *dev, const char *fn, const int skip_insert)
} else
dev->drv->base = 0;
dev->drv->supported = 0;
for (uint8_t i = 0; i < KNOWN_MO_TYPES; i++) {
if (size == (mo_types[i].sectors * mo_types[i].bytes_per_sector)) {
if (size == ((uint64_t) mo_types[i].sectors * mo_types[i].bytes_per_sector)) {
found = 1;
dev->drv->medium_size = mo_types[i].sectors;
dev->drv->sector_size = mo_types[i].bytes_per_sector;
dev->drv->supported = mo_drive_types[dev->drv->type].supported_media[i];
break;
}
}
if (found) {
if (fseek(dev->drv->fp, dev->drv->base, SEEK_SET) == -1)
if (fseeko64(dev->drv->fp, (uint64_t) dev->drv->base, SEEK_SET) == -1)
log_fatal(dev->log, "mo_load(): Error seeking to the beginning of "
"the file\n");
@@ -433,7 +437,8 @@ mo_update_request_length(mo_t *dev, int len, int block_len)
case 0xa8:
case 0xaa:
/* Round it to the nearest 2048 bytes. */
dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9;
dev->max_transfer_len = (dev->max_transfer_len / dev->drv->sector_size) *
dev->drv->sector_size;
/*
Make sure total length is not bigger than sum of the lengths of
@@ -481,19 +486,16 @@ mo_bus_speed(mo_t *dev)
{
double ret = -1.0;
if (dev && dev->drv && (dev->drv->bus_type == MO_BUS_SCSI)) {
dev->callback = -1.0; /* Speed depends on SCSI controller */
return 0.0;
} else {
if (dev && dev->drv)
ret = ide_atapi_get_period(dev->drv->ide_channel);
if (ret == -1.0) {
if (dev)
dev->callback = -1.0;
return 0.0;
} else
return ret * 1000000.0;
if (dev && dev->drv)
ret = ide_atapi_get_period(dev->drv->ide_channel);
if (ret == -1.0) {
if (dev)
dev->callback = -1.0;
ret = 0.0;
}
return ret;
}
static void
@@ -504,18 +506,10 @@ mo_command_common(mo_t *dev)
dev->tf->pos = 0;
if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0.0;
else {
double bytes_per_second;
if (dev->drv->bus_type == MO_BUS_SCSI) {
dev->callback = -1.0; /* Speed depends on SCSI controller */
return;
} else
bytes_per_second = mo_bus_speed(dev);
const double period = 1000000.0 / bytes_per_second;
dev->callback = period * (double) (dev->packet_len);
}
else if (dev->drv->bus_type == MO_BUS_SCSI)
dev->callback = -1.0; /* Speed depends on SCSI controller */
else
dev->callback = mo_bus_speed(dev) * (double) (dev->packet_len);
mo_set_callback(dev);
}
@@ -793,52 +787,54 @@ mo_invalid_field_pl(mo_t *dev, const uint32_t field)
}
static int
mo_blocks(mo_t *dev, int32_t *len, int out)
mo_blocks(mo_t *dev, int32_t *len, const int out)
{
int ret = 0;
int ret = 1;
*len = 0;
if (!dev->sector_len)
mo_command_complete(dev);
else {
if (dev->sector_len > 0) {
mo_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read",
dev->requested_blocks, dev->sector_pos);
if (dev->sector_pos >= dev->drv->medium_size) {
mo_log(dev->log, "Trying to %s beyond the end of disk\n", out ? "write" : "read");
if (!dev->drv->supported) {
mo_log(dev->log, "Trying to %s an unsupported medium\n",
out ? "write" : "read");
out ? mo_write_error(dev) : mo_read_error(dev);
ret = 0;
} else if (dev->sector_pos >= dev->drv->medium_size) {
mo_log(dev->log, "Trying to %s beyond the end of disk\n",
out ? "write" : "read");
mo_lba_out_of_range(dev);
ret = 0;
} else {
*len = dev->requested_blocks * dev->drv->sector_size;
ret = 1;
*len = dev->requested_blocks * dev->drv->sector_size;
for (int i = 0; i < dev->requested_blocks; i++) {
if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size) + (i * dev->drv->sector_size), SEEK_SET) == -1) {
if (fseeko64(dev->drv->fp, (uint64_t) dev->drv->base +
(uint64_t) (dev->sector_pos * dev->drv->sector_size),
SEEK_SET) == -1) {
if (out)
mo_write_error(dev);
else
mo_read_error(dev);
ret = -1;
} else {
if (!feof(dev->drv->fp))
if (feof(dev->drv->fp))
break;
if (out) {
if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1,
dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) {
dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) {
mo_log(dev->log, "mo_blocks(): Error writing data\n");
mo_write_error(dev);
ret = -1;
} else
fflush(dev->drv->fp);
} else {
if (fread(dev->buffer + (i * dev->drv->sector_size), 1,
dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) {
mo_log(dev->log, "mo_blocks(): Error reading data\n");
mo_read_error(dev);
ret = -1;
}
} else if (fread(dev->buffer + (i * dev->drv->sector_size), 1,
dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) {
mo_log(dev->log, "mo_blocks(): Error reading data\n");
mo_read_error(dev);
ret = -1;
}
}
@@ -849,11 +845,15 @@ mo_blocks(mo_t *dev, int32_t *len, int out)
}
if (ret == 1) {
mo_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" : "Read", *len);
mo_log(dev->log, "%s %i bytes of blocks...\n", out ? "Written" :
"Read", *len);
dev->sector_len -= dev->requested_blocks;
}
}
} else {
mo_command_complete(dev);
ret = 0;
}
return ret;
@@ -888,8 +888,8 @@ mo_format(mo_t *dev)
mo_log(dev->log, "Formatting media...\n");
fseek(dev->drv->fp, 0, SEEK_END);
long size = ftell(dev->drv->fp);
fseeko64(dev->drv->fp, 0, SEEK_END);
int64_t size = ftello64(dev->drv->fp);
#ifdef _WIN32
LARGE_INTEGER liSize;
@@ -953,7 +953,11 @@ mo_erase(mo_t *dev)
mo_log(dev->log, "Erasing %i blocks starting from %i...\n",
dev->sector_len, dev->sector_pos);
if (dev->sector_pos >= dev->drv->medium_size) {
if (!dev->drv->supported) {
mo_log(dev->log, "Trying to erase an unsupported medium\n");
mo_write_error(dev);
return 0;
} else if (dev->sector_pos >= dev->drv->medium_size) {
mo_log(dev->log, "Trying to erase beyond the end of disk\n");
mo_lba_out_of_range(dev);
return 0;
@@ -962,8 +966,9 @@ mo_erase(mo_t *dev)
mo_buf_alloc(dev, dev->drv->sector_size);
memset(dev->buffer, 0, dev->drv->sector_size);
fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos * dev->drv->sector_size),
SEEK_SET);
fseeko64(dev->drv->fp, dev->drv->base +
((uint64_t) dev->sector_pos * dev->drv->sector_size),
SEEK_SET);
for (i = 0; i < dev->requested_blocks; i++) {
if (feof(dev->drv->fp))
@@ -1347,6 +1352,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
mo_buf_alloc(dev, dev->packet_len);
const int ret = mo_blocks(dev, &alloc_length, 0);
alloc_length = dev->requested_blocks * dev->drv->sector_size;
if (ret > 0) {
dev->requested_blocks = max_len;
@@ -1383,6 +1389,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
mo_set_phase(dev, SCSI_PHASE_STATUS);
mo_command_complete(dev);
break;
} else if (!dev->drv->supported) {
mo_read_error(dev);
break;
}
fallthrough;
case GPCMD_WRITE_6:
@@ -1391,7 +1400,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
case GPCMD_WRITE_12:
case GPCMD_WRITE_AND_VERIFY_12:
mo_set_phase(dev, SCSI_PHASE_DATA_OUT);
alloc_length = 512;
alloc_length = dev->drv->sector_size;
switch (cdb[0]) {
case GPCMD_VERIFY_6:
@@ -1430,7 +1439,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
break;
}
if (dev->sector_pos > (mo_types[dev->drv->type].sectors - 1))
if (!dev->drv->supported)
mo_write_error(dev);
else if (dev->sector_pos >= dev->drv->medium_size)
mo_lba_out_of_range(dev);
else {
if (dev->sector_len) {
@@ -1441,11 +1452,11 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
mo_buf_alloc(dev, dev->packet_len);
dev->requested_blocks = max_len;
dev->packet_len = max_len << 9;
dev->packet_len = max_len * dev->drv->sector_size;
mo_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len);
mo_data_command_finish(dev, dev->packet_len, 512,
mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size,
dev->packet_len, 1);
ui_sb_update_icon(SB_MO | dev->id,
@@ -1462,7 +1473,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
case GPCMD_WRITE_SAME_10:
mo_set_phase(dev, SCSI_PHASE_DATA_OUT);
alloc_length = 512;
alloc_length = dev->drv->sector_size;
if ((cdb[1] & 6) == 6)
mo_invalid_field(dev, cdb[1]);
@@ -1470,7 +1481,9 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
dev->sector_len = (cdb[7] << 8) | cdb[8];
dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
if (dev->sector_pos > (mo_types[dev->drv->type].sectors - 1))
if (!dev->drv->supported)
mo_write_error(dev);
else if (dev->sector_pos >= dev->drv->medium_size)
mo_lba_out_of_range(dev);
else if (dev->sector_len) {
mo_buf_alloc(dev, alloc_length);
@@ -1481,7 +1494,8 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
mo_set_phase(dev, SCSI_PHASE_DATA_OUT);
mo_data_command_finish(dev, 512, 512,
mo_data_command_finish(dev, dev->drv->sector_size,
dev->drv->sector_size,
alloc_length, 1);
ui_sb_update_icon(SB_MO | dev->id,
@@ -1830,7 +1844,7 @@ static uint8_t
mo_phase_data_out(scsi_common_t *sc)
{
mo_t * dev = (mo_t *) sc;
const uint32_t last_sector = mo_types[dev->drv->type].sectors - 1;
const uint32_t last_sector = dev->drv->medium_size - 1;
int len = 0;
uint8_t error = 0;
uint32_t last_to_write;
@@ -1878,7 +1892,8 @@ mo_phase_data_out(scsi_common_t *sc)
dev->buffer[6] = (s >> 8) & 0xff;
dev->buffer[7] = s & 0xff;
}
if (fseek(dev->drv->fp, (i * dev->drv->sector_size), SEEK_SET) == -1)
if (fseeko64(dev->drv->fp,
((uint64_t) i * dev->drv->sector_size), SEEK_SET) == -1)
mo_write_error(dev);
if (feof(dev->drv->fp))
break;
@@ -1912,6 +1927,9 @@ mo_phase_data_out(scsi_common_t *sc)
block_desc_len = 0;
pos = hdr_len + block_desc_len;
mo_log(dev->log, "Block descriptor: %08X %08X %08X %08X %08X %08X %08X %08X\n",
dev->buffer[hdr_len], dev->buffer[hdr_len + 1], dev->buffer[hdr_len + 2], dev->buffer[hdr_len + 3],
dev->buffer[hdr_len + 4], dev->buffer[hdr_len + 5], dev->buffer[hdr_len + 6], dev->buffer[hdr_len + 7]);
while (1) {
if (pos >= param_list_len) {

View File

@@ -53,7 +53,7 @@ const uint8_t zip_command_flags[0x100] = {
[0x0c] = IMPLEMENTED,
[0x0d] = IMPLEMENTED | ATAPI_ONLY,
[0x12] = IMPLEMENTED | ALLOW_UA,
[0x13] = IMPLEMENTED | CHECK_READY | SCSI_ONLY,
[0x13] = IMPLEMENTED | CHECK_READY,
[0x15] = IMPLEMENTED,
[0x16 ... 0x17] = IMPLEMENTED | SCSI_ONLY,
[0x1a] = IMPLEMENTED,
@@ -64,8 +64,7 @@ const uint8_t zip_command_flags[0x100] = {
[0x25] = IMPLEMENTED | CHECK_READY,
[0x28] = IMPLEMENTED | CHECK_READY,
[0x2a ... 0x2b] = IMPLEMENTED | CHECK_READY,
[0x2e] = IMPLEMENTED | CHECK_READY,
[0x2f] = IMPLEMENTED | CHECK_READY | SCSI_ONLY,
[0x2e ... 0x2f] = IMPLEMENTED | CHECK_READY,
[0x41] = IMPLEMENTED | CHECK_READY,
[0x55] = IMPLEMENTED,
[0x5a] = IMPLEMENTED,
@@ -568,19 +567,16 @@ zip_bus_speed(zip_t *dev)
{
double ret = -1.0;
if (dev && dev->drv && (dev->drv->bus_type == ZIP_BUS_SCSI)) {
dev->callback = -1.0; /* Speed depends on SCSI controller */
return 0.0;
} else {
if (dev && dev->drv)
ret = ide_atapi_get_period(dev->drv->ide_channel);
if (ret == -1.0) {
if (dev)
dev->callback = -1.0;
return 0.0;
} else
return ret * 1000000.0;
if (dev && dev->drv)
ret = ide_atapi_get_period(dev->drv->ide_channel);
if (ret == -1.0) {
if (dev)
dev->callback = -1.0;
ret = 0.0;
}
return ret;
}
static void
@@ -591,18 +587,10 @@ zip_command_common(zip_t *dev)
dev->tf->pos = 0;
if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0.0;
else {
double bytes_per_second;
if (dev->drv->bus_type == ZIP_BUS_SCSI) {
dev->callback = -1.0; /* Speed depends on SCSI controller */
return;
} else
bytes_per_second = zip_bus_speed(dev);
double period = 1000000.0 / bytes_per_second;
dev->callback = period * (double) (dev->packet_len);
}
else if (dev->drv->bus_type == ZIP_BUS_SCSI)
dev->callback = -1.0; /* Speed depends on SCSI controller */
else
dev->callback = zip_bus_speed(dev) * (double) (dev->packet_len);
zip_set_callback(dev);
}
@@ -898,9 +886,7 @@ zip_blocks(zip_t *dev, int32_t *len, const int out)
int ret = 1;
*len = 0;
if (!dev->sector_len)
zip_command_complete(dev);
else {
if (dev->sector_len > 0) {
zip_log(dev->log, "%sing %i blocks starting from %i...\n", out ? "Writ" : "Read",
dev->requested_blocks, dev->sector_pos);
@@ -908,12 +894,13 @@ zip_blocks(zip_t *dev, int32_t *len, const int out)
zip_log(dev->log, "Trying to %s beyond the end of disk\n",
out ? "write" : "read");
zip_lba_out_of_range(dev);
ret = 0;
} else {
*len = dev->requested_blocks << 9;
for (int i = 0; i < dev->requested_blocks; i++) {
if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos << 9) +
(i << 9), SEEK_SET) == -1) {
if (fseek(dev->drv->fp, dev->drv->base + (dev->sector_pos << 9),
SEEK_SET) == -1) {
if (out)
zip_write_error(dev);
else
@@ -952,6 +939,9 @@ zip_blocks(zip_t *dev, int32_t *len, const int out)
dev->sector_len -= dev->requested_blocks;
}
}
} else {
zip_command_complete(dev);
ret = 0;
}
return ret;
@@ -1385,10 +1375,8 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb)
dev->packet_len = max_len * alloc_length;
zip_buf_alloc(dev, dev->packet_len);
int ret = 0;
if (dev->sector_len > 0)
ret = zip_blocks(dev, &alloc_length, 0);
const int ret = zip_blocks(dev, &alloc_length, 0);
alloc_length = dev->requested_blocks * 512;
if (ret > 0) {
dev->requested_blocks = max_len;

View File

@@ -105,6 +105,8 @@ static fdc_cards_t fdc_cards[] = {
// clang-format off
{ &device_none },
{ &device_internal },
{ &fdc_xt_device },
{ &fdc_at_device },
{ &fdc_b215_device },
{ &fdc_pii151b_device },
{ &fdc_pii158b_device },

View File

@@ -47,57 +47,6 @@ typedef struct monster_fdc_t {
char nvr_path[64];
} monster_fdc_t;
static void
rom_write(uint32_t addr, uint8_t val, void *priv)
{
const rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: read byte from BIOS at %06lX\n", addr);
#endif
if (addr < rom->mapping.base)
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
static void
rom_writew(uint32_t addr, uint16_t val, void *priv)
{
rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: read word from BIOS at %06lX\n", addr);
#endif
if (addr < (rom->mapping.base - 1))
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
*(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
static void
rom_writel(uint32_t addr, uint32_t val, void *priv)
{
rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: read long from BIOS at %06lX\n", addr);
#endif
if (addr < (rom->mapping.base - 3))
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
*(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
static void
monster_fdc_close(void *priv)
{

View File

@@ -28,6 +28,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/crc.h>
#include <86box/dma.h>
#include <86box/nvr.h>
#include <86box/random.h>
@@ -223,6 +224,7 @@ typedef struct d86f_t {
uint8_t *filebuf;
uint8_t *outbuf;
sector_t *last_side_sector[2];
uint16_t crc_table[256];
} d86f_t;
static const uint8_t encoded_fm[64] = {
@@ -247,7 +249,6 @@ static const uint8_t encoded_mfm[64] = {
};
static d86f_t *d86f[FDD_NUM];
static uint16_t CRCTable[256];
static fdc_t *d86f_fdc;
uint64_t poly = 0x42F0E1EBA9EA3693LL; /* ECMA normal */
@@ -276,28 +277,6 @@ d86f_log(const char *fmt, ...)
# define d86f_log(fmt, ...)
#endif
static void
setup_crc(uint16_t poly)
{
int c = 256;
int bc;
uint16_t temp;
while (c--) {
temp = c << 8;
bc = 8;
while (bc--) {
if (temp & 0x8000)
temp = (temp << 1) ^ poly;
else
temp <<= 1;
CRCTable[c] = temp;
}
}
}
void
d86f_destroy_linked_lists(int drive, int side)
{
@@ -1237,16 +1216,10 @@ decodefm(UNUSED(int drive), uint16_t dat)
return temp;
}
void
fdd_calccrc(uint8_t byte, crc_t *crc_var)
{
crc_var->word = (crc_var->word << 8) ^ CRCTable[(crc_var->word >> 8) ^ byte];
}
static void
d86f_calccrc(d86f_t *dev, uint8_t byte)
{
fdd_calccrc(byte, &(dev->calc_crc));
crc16_calc(dev->crc_table, byte, &(dev->calc_crc));
}
int
@@ -1274,7 +1247,9 @@ 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 wrong_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];
@@ -1282,7 +1257,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
if (dev->last_word[side] == req_am) {
dev->calc_crc.word = 0xFFFF;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained =
find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
@@ -1302,7 +1278,8 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui
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));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
if (ignore_other_am & 1) {
@@ -1378,7 +1355,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
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;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
dev->preceding_bit[side] = dev->last_word[side] & 1;
@@ -1390,7 +1368,8 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u
if ((ignore_other_am & 2) && (dev->last_word[side] == other_am) && (find->sync_marks >= 3)) {
if (d86f_word_is_aligned(drive, side, find->sync_pos)) {
dev->calc_crc.word = 0xCDB4;
fdd_calccrc(decodefm(drive, dev->last_word[side]), &(dev->calc_crc));
crc16_calc(dev->crc_table, decodefm(drive, dev->last_word[side]),
&(dev->calc_crc));
find->sync_marks = find->bits_obtained = find->bytes_obtained = 0;
find->sync_pos = 0xFFFFFFFF;
if (ignore_other_am & 1) {
@@ -1464,8 +1443,11 @@ d86f_read_sector_id(int drive, int side, int match)
if (dev->id_find.bytes_obtained < 4) {
dev->last_sector.byte_array[dev->id_find.bytes_obtained] =
decodefm(drive, dev->last_word[side]);
fdd_calccrc(dev->last_sector.byte_array[dev->id_find.bytes_obtained], &(dev->calc_crc));
} else if ((dev->id_find.bytes_obtained >= 4) && (dev->id_find.bytes_obtained < 6)) {
crc16_calc(dev->crc_table,
dev->last_sector.byte_array[dev->id_find.bytes_obtained],
&(dev->calc_crc));
} else if ((dev->id_find.bytes_obtained >= 4) &&
(dev->id_find.bytes_obtained < 6)) {
dev->track_crc.bytes[(dev->id_find.bytes_obtained & 1) ^ 1] =
decodefm(drive, dev->last_word[side]);
}
@@ -1643,7 +1625,7 @@ d86f_read_sector_data(int drive, int side)
}
}
}
fdd_calccrc(data, &(dev->calc_crc));
crc16_calc(dev->crc_table, data, &(dev->calc_crc));
} else if (dev->data_find.bytes_obtained < crc_pos)
dev->track_crc.bytes[(dev->data_find.bytes_obtained - sector_len) ^ 1] =
decodefm(drive, dev->last_word[side]);
@@ -1730,11 +1712,12 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am)
if (dev->data_find.bytes_obtained < sector_len) {
/* This is a data byte, so CRC it. */
if (!dev->data_find.bytes_obtained) {
fdd_calccrc(decodefm(drive, am), &(dev->calc_crc));
} else {
fdd_calccrc(dev->current_byte[side], &(dev->calc_crc));
}
if (!dev->data_find.bytes_obtained)
crc16_calc(dev->crc_table, decodefm(drive, am),
&(dev->calc_crc));
else
crc16_calc(dev->crc_table, dev->current_byte[side],
&(dev->calc_crc));
}
}
} else {
@@ -3861,8 +3844,6 @@ d86f_load(int drive, char *fn)
void
d86f_init(void)
{
setup_crc(0x1021);
for (uint8_t i = 0; i < FDD_NUM; i++)
d86f[i] = NULL;
}
@@ -3926,6 +3907,8 @@ d86f_setup(int drive)
dev->last_side_sector[0] = NULL;
dev->last_side_sector[1] = NULL;
crc16_setup(dev->crc_table, 0x1021);
/* Set the drive as active. */
d86f[drive] = dev;
}

View File

@@ -88,18 +88,20 @@ static const joystick_if_t joystick_none = {
static const struct {
const joystick_if_t *joystick;
} joysticks[] = {
{ &joystick_none },
{ &joystick_2axis_2button },
{ &joystick_2axis_4button },
{ &joystick_2axis_6button },
{ &joystick_2axis_8button },
{ &joystick_3axis_2button },
{ &joystick_3axis_4button },
{ &joystick_4axis_4button },
{ &joystick_ch_flightstick_pro },
{ &joystick_sw_pad },
{ &joystick_tm_fcs },
{ NULL }
{ &joystick_none },
{ &joystick_2axis_2button },
{ &joystick_2axis_4button },
{ &joystick_2axis_6button },
{ &joystick_2axis_8button },
{ &joystick_3axis_2button },
{ &joystick_3axis_4button },
{ &joystick_4axis_4button },
{ &joystick_ch_flightstick_pro },
{ &joystick_ch_flightstick_pro_ch_pedals },
{ &joystick_sw_pad },
{ &joystick_tm_fcs },
{ &joystick_tm_fcs_rcs },
{ NULL }
};
static joystick_instance_t *joystick_instance[GAMEPORT_MAX] = { NULL, NULL };

View File

@@ -112,6 +112,26 @@ ch_flightstick_pro_read_axis(UNUSED(void *priv), int axis)
}
}
static int
ch_flightstick_pro_ch_pedals_read_axis(UNUSED(void *priv), int axis)
{
if (!JOYSTICK_PRESENT(0, 0))
return AXIS_NOT_PRESENT;
switch (axis) {
case 0:
return joystick_state[0][0].axis[0];
case 1:
return joystick_state[0][0].axis[1];
case 2:
return joystick_state[0][0].axis[3];
case 3:
return joystick_state[0][0].axis[2];
default:
return 0;
}
}
static void
ch_flightstick_pro_a0_over(UNUSED(void *priv))
{
@@ -135,3 +155,21 @@ const joystick_if_t joystick_ch_flightstick_pro = {
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { "POV" }
};
const joystick_if_t joystick_ch_flightstick_pro_ch_pedals = {
.name = "CH Flightstick Pro + CH Pedals",
.internal_name = "ch_flightstick_pro_ch_pedals",
.init = ch_flightstick_pro_init,
.close = ch_flightstick_pro_close,
.read = ch_flightstick_pro_read,
.write = ch_flightstick_pro_write,
.read_axis = ch_flightstick_pro_ch_pedals_read_axis,
.a0_over = ch_flightstick_pro_a0_over,
.axis_count = 4,
.button_count = 4,
.pov_count = 1,
.max_joysticks = 1,
.axis_names = { "X axis", "Y axis", "Throttle", "Rudder" },
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { "POV" }
};

View File

@@ -112,6 +112,36 @@ tm_fcs_read_axis(UNUSED(void *priv), int axis)
}
}
static int
tm_fcs_rcs_read_axis(UNUSED(void *priv), int axis)
{
if (!JOYSTICK_PRESENT(0, 0))
return AXIS_NOT_PRESENT;
switch (axis) {
case 0:
return joystick_state[0][0].axis[0];
case 1:
return joystick_state[0][0].axis[1];
case 2:
return joystick_state[0][0].axis[2];
case 3:
if (joystick_state[0][0].pov[0] == -1)
return 32767;
if (joystick_state[0][0].pov[0] > 315 || joystick_state[0][0].pov[0] < 45)
return -32768;
if (joystick_state[0][0].pov[0] >= 45 && joystick_state[0][0].pov[0] < 135)
return -16384;
if (joystick_state[0][0].pov[0] >= 135 && joystick_state[0][0].pov[0] < 225)
return 0;
if (joystick_state[0][0].pov[0] >= 225 && joystick_state[0][0].pov[0] < 315)
return 16384;
return 0;
default:
return 0;
}
}
static void
tm_fcs_a0_over(UNUSED(void *priv))
{
@@ -135,3 +165,21 @@ const joystick_if_t joystick_tm_fcs = {
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { "POV" }
};
const joystick_if_t joystick_tm_fcs_rcs = {
.name = "Thrustmaster FCS + Rudder Control System",
.internal_name = "thrustmaster_fcs_rcs",
.init = tm_fcs_init,
.close = tm_fcs_close,
.read = tm_fcs_read,
.write = tm_fcs_write,
.read_axis = tm_fcs_rcs_read_axis,
.a0_over = tm_fcs_a0_over,
.axis_count = 3,
.button_count = 4,
.pov_count = 1,
.max_joysticks = 1,
.axis_names = { "X axis", "Y axis", "Rudder" },
.button_names = { "Button 1", "Button 2", "Button 3", "Button 4" },
.pov_names = { "POV" }
};

View File

@@ -20,6 +20,11 @@
#ifndef EMU_86BOX_H
#define EMU_86BOX_H
#if defined(__NetBSD__) || defined(__OpenBSD__)
/* Doesn't compile on NetBSD/OpenBSD without this include */
#include <stdarg.h>
#endif
/* Configuration values. */
#define GFXCARD_MAX 2
#define SERIAL_MAX 7
@@ -107,6 +112,7 @@ extern uint64_t instru_run_ms;
#define window_y monitor_settings[0].mon_window_y
#define window_w monitor_settings[0].mon_window_w
#define window_h monitor_settings[0].mon_window_h
extern int inhibit_multimedia_keys; /* (C) Inhibit multimedia keys on Windows. */
extern int window_remember;
extern int vid_resize; /* (C) allow resizing */
extern int invert_display; /* (C) invert the display */
@@ -126,7 +132,6 @@ extern int video_filter_method; /* (C) video */
extern int video_vsync; /* (C) video */
extern int video_framerate; /* (C) video */
extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */
extern char video_shader[512]; /* (C) video */
extern int bugger_enabled; /* (C) enable ISAbugger */
extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */
extern int postcard_enabled; /* (C) enable POST card */
@@ -188,19 +193,18 @@ extern FILE *stdlog; /* file to log output to */
#endif
extern int config_changed; /* config has changed */
extern __thread int is_cpu_thread; /* Is this the CPU thread? */
/* Function prototypes. */
#ifdef HAVE_STDARG_H
extern void pclog_ex(const char *fmt, va_list ap);
extern void fatal_ex(const char *fmt, va_list ap);
extern void warning_ex(const char *fmt, va_list ap);
#endif
extern void pclog_toggle_suppr(void);
#ifdef _MSC_VER
extern void pclog(const char *fmt, ...);
extern void fatal(const char *fmt, ...);
#else
extern void pclog(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void fatal(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
#endif
extern void warning(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void set_screen_size(int x, int y);
extern void set_screen_size_monitor(int x, int y, int monitor_index);
extern void reset_screen_size(void);

View File

@@ -35,13 +35,12 @@
* USA.
*/
#ifndef __NetBSD__
#ifndef BSWAP_H
#define BSWAP_H
#include <stdint.h>
#ifndef __NetBSD__
#define bswap_16(x) \
((uint16_t)((((x) & 0x00ffu) << 8) | \
(((x) & 0xff00u) >> 8)))
@@ -91,6 +90,7 @@ bswap64(uint64_t x)
return bswap_16(x);
#endif
}
#endif
static __inline void
bswap16s(uint16_t *s)
@@ -241,5 +241,3 @@ cpu_to_be32wu(uint32_t *p, uint32_t v)
#undef be_bswaps
#endif /*BSWAP_H*/
#endif

View File

@@ -28,8 +28,9 @@
#define CD_STATUS_PLAYING 5
#define CD_STATUS_STOPPED 6
#define CD_STATUS_PLAYING_COMPLETED 7
#define CD_STATUS_HAS_AUDIO 4
#define CD_STATUS_MASK 7
#define CD_STATUS_HOLD 8
#define CD_STATUS_HAS_AUDIO 0xc
#define CD_STATUS_MASK 0xf
/* Medium changed flag. */
#define CD_STATUS_TRANSITION 0x40
@@ -50,8 +51,6 @@
#define CD_IMAGE_HISTORY 10
#define BUF_SIZE 32768
#define CDROM_IMAGE 200
/* This is so that if/when this is changed to something else,
@@ -63,6 +62,8 @@
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define CD_BUF_SIZE (16 * RAW_SECTOR_SIZE)
#define DATA_TRACK 0x14
#define AUDIO_TRACK 0x10
@@ -105,9 +106,9 @@ enum {
#define CDV EMU_VERSION_EX
static const struct cdrom_drive_types_s {
const char vendor[9];
const char model[17];
const char revision[5];
const char * vendor;
const char * model;
const char * revision;
const char * internal_name;
const int bus_type;
/* SCSI standard for SCSI (or both) devices, early for IDE. */
@@ -298,9 +299,7 @@ typedef struct cdrom {
void * priv;
char image_path[1024];
char prev_image_path[1024];
char * image_history[CD_IMAGE_HISTORY];
char prev_image_path[1280];
uint32_t sound_on;
uint32_t cdrom_capacity;
@@ -310,18 +309,21 @@ typedef struct cdrom {
uint32_t type;
uint32_t sector_size;
int cd_buflen;
int audio_op;
int audio_muted_soft;
int sony_msf;
int real_speed;
int is_early;
int is_nec;
uint32_t inv_field;
int32_t cached_sector;
int32_t cd_buflen;
int32_t sony_msf;
int32_t real_speed;
int32_t is_early;
int32_t is_nec;
int32_t is_bcd;
int32_t cdrom_sector_size;
const cdrom_ops_t *ops;
char * image_history[CD_IMAGE_HISTORY];
void * local;
void * log;
@@ -330,22 +332,29 @@ typedef struct cdrom {
uint32_t (*get_volume)(void *p, int channel);
uint32_t (*get_channel)(void *p, int channel);
int16_t cd_buffer[BUF_SIZE];
int16_t cd_buffer[CD_BUF_SIZE];
uint8_t subch_buffer[96];
int cdrom_sector_size;
/* Needs some extra breathing space in case of overflows. */
uint8_t raw_buffer[4096];
uint8_t raw_buffer[2][4096];
uint8_t extra_buffer[296];
int32_t is_chinon;
int32_t is_pioneer;
int32_t is_plextor;
int32_t is_sony;
int32_t is_toshiba;
int32_t c2_first;
int32_t cur_buf;
/* Only used on Windows hosts for disc change notifications. */
uint8_t host_letter;
} cdrom_t;
extern cdrom_t cdrom[CDROM_NUM];
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
static __inline int
@@ -366,8 +375,6 @@ extern char *cdrom_get_revision(const int type);
extern int cdrom_get_scsi_std(const int type);
extern int cdrom_is_early(const int type);
extern int cdrom_is_generic(const int type);
extern int cdrom_has_date(const int type);
extern int cdrom_is_sony(const int type);
extern int cdrom_is_caddy(const int type);
extern int cdrom_get_speed(const int type);
extern int cdrom_get_inquiry_len(const int type);
@@ -384,6 +391,7 @@ extern void cdrom_set_type(const int model, const int type);
extern int cdrom_get_type(const int model);
extern int cdrom_lba_to_msf_accurate(const int lba);
extern void cdrom_interleave_subch(uint8_t *d, const uint8_t *s);
extern double cdrom_seek_time(const cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev);
extern void cdrom_seek(cdrom_t *dev, const uint32_t pos, const uint8_t vendor_type);
@@ -396,7 +404,7 @@ extern uint8_t cdrom_audio_track_search(cdrom_t *dev, const uint32_t pos
extern uint8_t cdrom_audio_track_search_pioneer(cdrom_t *dev, const uint32_t pos, const uint8_t playbit);
extern uint8_t cdrom_audio_play_pioneer(cdrom_t *dev, const uint32_t pos);
extern uint8_t cdrom_audio_play_toshiba(cdrom_t *dev, const uint32_t pos, const int type);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos, const int type);
extern uint8_t cdrom_audio_scan(cdrom_t *dev, const uint32_t pos);
extern void cdrom_audio_pause_resume(cdrom_t *dev, const uint8_t resume);
extern uint8_t cdrom_get_current_status(const cdrom_t *dev);
@@ -424,6 +432,7 @@ extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_
uint8_t *buffer, uint32_t *info);
extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer);
extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer);
extern uint8_t cdrom_get_current_mode(cdrom_t *dev);
extern void cdrom_set_empty(cdrom_t *dev);
extern void cdrom_update_status(cdrom_t *dev);
extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert);
@@ -437,6 +446,8 @@ extern int cdrom_is_empty(const uint8_t id);
extern void cdrom_eject(const uint8_t id);
extern void cdrom_reload(const uint8_t id);
extern int cdrom_assigned_letters;
#ifdef __cplusplus
}
#endif

View File

@@ -48,6 +48,7 @@ extern const device_t contaq_82c597_device;
/* C&T */
extern const device_t ct_82c100_device;
extern const device_t neat_device;
extern const device_t neat_sx_device;
extern const device_t scat_device;
extern const device_t scat_4_device;
extern const device_t scat_sx_device;

34
src/include/86box/crc.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* 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.
*
* Definitions for the CRC code.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2025 Miran Grca.
*/
#ifndef EMU_CRC_H
#define EMU_CRC_H
#ifdef __cplusplus
extern "C" {
#endif
typedef union {
uint16_t word;
uint8_t bytes[2];
} crc_t;
extern void crc16_setup(uint16_t *crc_table, uint16_t poly);
extern void crc16_calc(uint16_t *crc_table, uint8_t byte, crc_t *crc_var);
#ifdef __cplusplus
}
#endif
#endif /*EMU_CRC_H*/

View File

@@ -137,12 +137,11 @@ typedef struct device_config_spinner_t {
typedef struct device_config_bios_t {
const char *name;
const char *internal_name;
int bios_type;
int files_no;
uint8_t bios_type;
uint8_t files_no;
uint32_t local;
uint32_t size;
void *dev1;
void *dev2;
void *dev[2];
const char *files[9];
} device_config_bios_t;
@@ -154,7 +153,7 @@ typedef struct _device_config_ {
int default_int;
const char *file_filter;
const device_config_spinner_t spinner;
const device_config_selection_t selection[32];
const device_config_selection_t selection[64];
const device_config_bios_t bios[32];
} device_config_t;
@@ -211,6 +210,11 @@ extern void device_speed_changed(void);
extern void device_force_redraw(void);
extern void device_get_name(const device_t *dev, int bus, char *name);
extern int device_has_config(const device_t *dev);
extern uint8_t device_get_bios_type(const device_t *dev, const char *internal_name);
extern uint8_t device_get_bios_num_files(const device_t *dev, const char *internal_name);
extern uint32_t device_get_bios_local(const device_t *dev, const char *internal_name);
extern uint32_t device_get_bios_file_size(const device_t *dev, const char *internal_name);
extern const char *device_get_bios_file(const device_t *dev, const char *internal_name, int file_no);
extern int device_is_valid(const device_t *, int mch);

View File

@@ -8,15 +8,13 @@
*
* Definitions for the floppy drive emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
* Copyright 2008-2025 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2018-2025 Fred N. van Kempen.
*/
#ifndef EMU_FDD_H
#define EMU_FDD_H
@@ -129,13 +127,6 @@ extern int drive_empty[FDD_NUM];
#define SECTOR_FIRST -2
#define SECTOR_NEXT -1
typedef union {
uint16_t word;
uint8_t bytes[2];
} crc_t;
void fdd_calccrc(uint8_t byte, crc_t *crc_var);
typedef struct d86f_handler_t {
uint16_t (*disk_flags)(int drive);
uint16_t (*side_flags)(int drive);

View File

@@ -179,10 +179,12 @@ extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
extern const joystick_if_t joystick_ch_flightstick_pro;
extern const joystick_if_t joystick_ch_flightstick_pro_ch_pedals;
extern const joystick_if_t joystick_sw_pad;
extern const joystick_if_t joystick_tm_fcs;
extern const joystick_if_t joystick_tm_fcs_rcs;
extern int gameport_available(int);
extern int gameport_has_config(int);

View File

@@ -99,10 +99,12 @@ extern const device_t mcide_device;
extern const device_t xta_wdxt150_device; /* xta_wdxt150 */
extern const device_t xta_hd20_device; /* EuroPC internal */
extern const device_t xtide_device; /* xtide_xt */
extern const device_t xtide_at_device; /* xtide_at */
extern const device_t xtide_acculogic_device; /* xtide_ps2 */
extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */
extern const device_t xtide_device; /* xtide_xt */
extern const device_t xtide_at_device; /* xtide_at */
extern const device_t xtide_at_2ch_device; /* xtide_at_2ch */
extern const device_t xtide_acculogic_device; /* xtide_ps2 */
extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */
extern const device_t xtide_at_ps2_2ch_device; /* xtide_at_ps2_2ch */
/* Miscellaneous */
extern const device_t lba_enhancer_device;

View File

@@ -133,6 +133,8 @@ typedef struct ide_s {
uint8_t (*phase_data_out)(scsi_common_t *sc);
void (*command_stop)(scsi_common_t *sc);
void (*bus_master_error)(scsi_common_t *sc);
void (*read)(scsi_common_t *sc);
void (*write)(scsi_common_t *sc);
#else
void * get_max;
void * get_timings;
@@ -199,7 +201,7 @@ extern uint8_t ide_read_alt_status(uint16_t addr, void *priv);
extern uint16_t ide_readw(uint16_t addr, void *priv);
extern void ide_set_bus_master(int board,
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv),
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv),
void (*set_irq)(uint8_t status, void *priv), void *priv);
extern void win_cdrom_eject(uint8_t id);

View File

@@ -63,7 +63,7 @@ extern const device_t sff8038i_device;
extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base);
extern void sff_bus_master_set_irq(uint8_t status, void *priv);
extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv);
extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv);
extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t sff_bus_master_read(uint16_t port, void *priv);

View File

@@ -138,55 +138,63 @@ typedef struct hdd_zone_t {
/* Define the virtual Hard Disk. */
typedef struct hard_disk_t {
uint8_t id;
uint8_t id;
union {
uint8_t channel; /* Needed for Settings to reduce the number of if's */
/* Needed for Settings to reduce the number of if's */
uint8_t channel;
uint8_t mfm_channel; /* Should rename and/or unionize */
uint8_t esdi_channel;
uint8_t xta_channel;
uint8_t ide_channel;
uint8_t scsi_id;
uint8_t mfm_channel;
uint8_t esdi_channel;
uint8_t xta_channel;
uint8_t ide_channel;
uint8_t scsi_id;
};
uint8_t bus_type;
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t wp; /* Disk has been mounted READ-ONLY */
uint8_t pad;
uint8_t pad0;
void *priv;
uint8_t bus_type;
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t wp; /* Disk has been mounted
READ-ONLY */
uint8_t pad;
uint8_t pad0;
char fn[1024]; /* Name of current image file */
char vhd_parent[1041]; /* Differential VHD parent file */
void * priv;
uint32_t seek_pos;
uint32_t seek_len;
uint32_t base;
uint32_t spt;
uint32_t hpc; /* Physical geometry parameters */
uint32_t tracks;
const char *model;
char fn[1024]; /* Name of current image file */
/* Differential VHD parent file */
char vhd_parent[1280];
hdd_zone_t zones[HDD_MAX_ZONES];
uint32_t num_zones;
hdd_cache_t cache;
uint32_t phy_cyl;
uint32_t phy_heads;
uint32_t rpm;
uint8_t max_multiple_block;
uint32_t seek_pos;
uint32_t seek_len;
uint32_t base;
uint32_t spt; /* Physical geometry parameters */
uint32_t hpc;
uint32_t tracks;
uint32_t speed_preset;
uint32_t cur_cylinder;
uint32_t cur_track;
uint32_t cur_addr;
uint32_t num_zones;
uint32_t phy_cyl;
uint32_t phy_heads;
uint32_t rpm;
uint32_t cur_cylinder;
uint32_t cur_track;
uint32_t cur_addr;
uint32_t vhd_blocksize;
uint32_t speed_preset;
uint32_t vhd_blocksize;
uint8_t max_multiple_block;
uint8_t pad1[3];
double avg_rotation_lat_usec;
double full_stroke_usec;
double head_switch_usec;
double cyl_switch_usec;
const char * model;
hdd_zone_t zones[HDD_MAX_ZONES];
hdd_cache_t cache;
double avg_rotation_lat_usec;
double full_stroke_usec;
double head_switch_usec;
double cyl_switch_usec;
} hard_disk_t;
extern hard_disk_t hdd[HDD_NUM];

View File

@@ -1,69 +0,0 @@
/*
* 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.
*
* 8080 CPU emulation (header).
*
*
*
* Authors: Cacodemon345
*
* Copyright 2022 Cacodemon345
*/
#include <stdint.h>
typedef struct i8080 {
union {
uint16_t af; /* Intended in case we also go for μPD9002 emulation, which also has a Z80 emulation mode. */
struct {
uint8_t a;
uint8_t flags;
};
};
union {
uint16_t bc;
struct {
uint8_t b;
uint8_t c;
};
};
union {
uint16_t de;
struct {
uint8_t d;
uint8_t e;
};
};
union {
uint16_t hl;
struct {
uint8_t h;
uint8_t l;
};
};
uint16_t pc;
uint16_t sp;
uint16_t oldpc;
uint16_t ei;
uint32_t pmembase;
uint32_t dmembase; /* Base from where i8080 starts. */
uint8_t emulated; /* 0 = not emulated, use separate registers, 1 = emulated, use x86 registers. */
uint16_t *cpu_flags;
void (*writemembyte)(uint32_t, uint8_t);
uint8_t (*readmembyte)(uint32_t);
void (*startclock)(void);
void (*endclock)(void);
void (*checkinterrupts)(void);
uint8_t (*fetchinstruction)(void *);
} i8080;
#define C_FLAG_I8080 (1 << 0)
#define P_FLAG_I8080 (1 << 2)
#define AC_FLAG_I8080 (1 << 4)
#define Z_FLAG_I8080 (1 << 6)
#define S_FLAG_I8080 (1 << 7)

View File

@@ -31,6 +31,7 @@ typedef void *ini_section_t;
extern ini_t ini_new(void);
extern ini_t ini_read(const char *fn);
extern void ini_strip_quotes(ini_t ini);
extern void ini_write(ini_t ini, const char *fn);
extern void ini_dump(ini_t ini);
extern void ini_close(ini_t ini);
@@ -58,6 +59,7 @@ extern void ini_section_set_hex20(ini_section_t section, const char *name, i
extern void ini_section_set_mac(ini_section_t section, const char *name, int val);
extern void ini_section_set_string(ini_section_t section, const char *name, const char *val);
extern void ini_section_set_wstring(ini_section_t section, const char *name, wchar_t *val);
extern int ini_has_entry(ini_section_t self, const char *name);
#define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name)

View File

@@ -54,16 +54,16 @@ typedef struct kbc_at_port_t {
typedef struct atkbc_dev_t {
const char *name; /* name of this device */
uint8_t type;
uint8_t command;
uint8_t last_scan_code;
uint8_t state;
uint8_t resolution;
uint8_t rate;
uint8_t cmd_queue_start;
uint8_t cmd_queue_end;
uint8_t queue_start;
uint8_t queue_end;
uint8_t type;
uint8_t command;
uint8_t last_scan_code;
uint8_t state;
uint8_t resolution;
uint8_t rate;
uint8_t cmd_queue_start;
uint8_t cmd_queue_end;
uint8_t queue_start;
uint8_t queue_end;
uint16_t flags;
@@ -234,6 +234,7 @@ extern const device_t keyboard_xtclone_device;
extern const device_t keyboard_at_device;
extern const device_t keyboard_at_ami_device;
extern const device_t keyboard_at_compaq_device;
extern const device_t keyboard_at_phoenix_device;
extern const device_t keyboard_at_ncr_device;
extern const device_t keyboard_at_olivetti_device;
extern const device_t keyboard_at_siemens_device;

View File

@@ -24,6 +24,11 @@
extern "C" {
# endif
#ifdef __NetBSD__
/* Doesn't compile on NetBSD without this include */
#include <stdarg.h>
#endif
#define LOG_SIZE_BUFFER 1024 /* Log size buffer */
#define LOG_SIZE_BUFFER_CYCLIC_LINES 32 /* Cyclic log size buffer (number of lines that should be cehcked) */
#define LOG_MINIMUM_REPEAT_ORDER 4 /* Minimum repeat size */
@@ -36,6 +41,7 @@ extern void log_out(void *priv, const char *fmt, va_list);
extern void log_out_cyclic(void* priv, const char *fmt, va_list);
#endif /*RELEASE_BUILD*/
extern void log_fatal(void *priv, const char *fmt, ...);
extern void log_warning(void *priv, const char *fmt, ...);
extern void *log_open(const char *dev_name);
extern void *log_open_cyclic(const char *dev_name);
extern void log_close(void *priv);

View File

@@ -208,7 +208,9 @@ enum {
MACHINE_CHIPSET_ALI_ALADDIN_V,
MACHINE_CHIPSET_ALI_ALADDIN_PRO_II,
MACHINE_CHIPSET_SCAT,
MACHINE_CHIPSET_SCAT_SX,
MACHINE_CHIPSET_NEAT,
MACHINE_CHIPSET_NEAT_SX,
MACHINE_CHIPSET_CT_386,
MACHINE_CHIPSET_CT_CS4031,
MACHINE_CHIPSET_CONTAQ_82C596,
@@ -493,6 +495,7 @@ extern int machine_at_adi386sx_init(const machine_t *);
extern int machine_at_cmdsl386sx16_init(const machine_t *);
extern int machine_at_cmdsl386sx25_init(const machine_t *);
extern int machine_at_dataexpert386sx_init(const machine_t *);
extern int machine_at_if386sx_init(const machine_t *);
extern int machine_at_spc6033p_init(const machine_t *);
extern int machine_at_wd76c10_init(const machine_t *);
extern int machine_at_arb1374_init(const machine_t *);
@@ -865,6 +868,7 @@ extern int machine_at_s1857_init(const machine_t *);
extern int machine_at_p6bap_init(const machine_t *);
extern int machine_at_p6bat_init(const machine_t *);
extern int machine_at_prosignias31x_bx_init(const machine_t *);
extern int machine_at_7sbb_init(const machine_t *);
/* m_at_misc.c */
extern int machine_at_vpc2007_init(const machine_t *);

View File

@@ -448,6 +448,7 @@ extern void mem_flush_write_page(uint32_t addr, uint32_t virt);
extern void mem_reset_page_blocks(void);
extern void flushmmucache(void);
extern void flushmmucache_write(void);
extern void flushmmucache_pc(void);
extern void flushmmucache_nopc(void);

View File

@@ -51,10 +51,10 @@ static const mo_type_t mo_types[KNOWN_MO_TYPES] = {
};
typedef struct mo_drive_type_t {
const char vendor[9];
const char model[16];
const char revision[5];
int8_t supported_media[KNOWN_MO_TYPES];
const char *vendor;
const char *model;
const char *revision;
int8_t supported_media[KNOWN_MO_TYPES];
} mo_drive_type_t;
#define KNOWN_MO_DRIVE_TYPES 22
@@ -122,6 +122,8 @@ typedef struct mo_drive_t {
uint32_t medium_size;
uint32_t base;
uint16_t sector_size;
int supported;
} mo_drive_t;
typedef struct mo_t {
@@ -161,6 +163,7 @@ typedef struct mo_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -100,6 +100,9 @@ extern void mouse_scale_axis(int axis, int val);
extern void mouse_set_z(int z);
extern void mouse_clear_z(void);
extern void mouse_subtract_z(int *delta_z, int min, int max, int invert);
extern void mouse_set_w(int w);
extern void mouse_clear_w(void);
extern void mouse_subtract_w(int *delta_w, int min, int max, int invert);
extern void mouse_set_buttons_ex(int b);
extern int mouse_get_buttons_ex(void);
extern void mouse_set_sample_rate(double new_rate);

View File

@@ -164,6 +164,7 @@ extern uint32_t plat_language_code(char *langcode);
extern void plat_language_code_r(uint32_t lcid, char *outbuf, int len);
extern void plat_get_cpu_string(char *outbuf, uint8_t len);
extern void plat_set_thread_name(void *thread, const char *name);
extern void plat_break(void);
/* Resource management. */
extern wchar_t *plat_get_string(int id);

158
src/include/86box/qt-glsl.h Normal file
View File

@@ -0,0 +1,158 @@
#ifndef SRC_WX_GLSL_H_
#define SRC_WX_GLSL_H_
#define MAX_PREV 7
#define MAX_SHADERS 20
#define MAX_TEXTURES 20
#define MAX_PARAMETERS 100
#define MAX_USER_SHADERS 20
//#define SDL2_SHADER_DEBUG
struct shader_scale {
int mode[2];
float value[2];
};
struct shader_state {
float input_size[2];
float input_texture_size[2];
float output_texture_size[2];
float output_size[2];
float tex_coords[8];
};
struct shader_vbo {
int vertex_coord;
int tex_coord;
int color;
};
struct shader_texture {
int id;
int width;
int height;
int type;
int internal_format;
int format;
int min_filter;
int mag_filter;
int wrap_mode;
void *data;
int mipmap;
};
struct shader_lut_texture {
char name[50];
struct shader_texture texture;
};
struct shader_fbo {
int id;
struct shader_texture texture;
int srgb;
int mipmap_input;
};
struct shader_prev {
struct shader_fbo fbo;
struct shader_vbo vbo;
};
struct shader_input {
int texture;
int input_size;
int texture_size;
int tex_coord;
};
struct shader_uniforms {
int mvp_matrix;
int vertex_coord;
int tex_coord;
int color;
int texture;
int input_size;
int texture_size;
int output_size;
int frame_count;
int frame_direction;
struct shader_input orig;
struct shader_input pass[MAX_SHADERS];
struct shader_input prev_pass[MAX_SHADERS];
struct shader_input prev[MAX_PREV];
int parameters[MAX_PARAMETERS];
int lut_textures[MAX_TEXTURES];
};
struct shader_program {
int vertex_shader;
int fragment_shader;
int id;
};
struct shader_parameter {
char id[64];
char description[64];
float default_value;
float value;
float min;
float max;
float step;
};
struct shader_pass {
int active;
char alias[64];
int vertex_array;
int frame_count_mod;
struct shader_program program;
struct shader_uniforms uniforms;
struct shader_fbo fbo;
struct shader_vbo vbo;
struct shader_state state;
struct shader_scale scale;
};
struct glsl_shader {
int active;
char name[64];
int num_passes;
struct shader_pass passes[MAX_SHADERS];
int num_lut_textures;
struct shader_lut_texture lut_textures[MAX_TEXTURES];
int num_parameters;
struct shader_parameter parameters[MAX_PARAMETERS];
struct shader_pass prev_scene;
struct shader_prev prev[MAX_PREV + 1];
int last_prev_update;
int has_prev;
float shader_refresh_rate;
int input_filter_linear;
};
typedef struct glsl_t {
int num_shaders;
struct glsl_shader shaders[MAX_USER_SHADERS];
struct shader_pass scene;
struct shader_pass final_pass;
struct shader_pass fs_color;
#ifdef SDL2_SHADER_DEBUG
struct shader_pass debug;
#endif
int srgb;
} glsl_t;
#endif

View File

@@ -0,0 +1,59 @@
#ifndef SRC_WX_GLSLP_PARSER_H_
#define SRC_WX_GLSLP_PARSER_H_
#include "qt-glsl.h"
struct parameter {
char id[64];
char description[64];
float default_value;
float value;
float min;
float max;
float step;
};
struct texture {
char path[256];
char name[50];
int linear;
int mipmap;
char wrap_mode[50];
};
struct shader {
char shader_fn[1024];
char *shader_program;
char alias[64];
int filter_linear;
int float_framebuffer;
int srgb_framebuffer;
int mipmap_input;
int frame_count_mod;
char wrap_mode[50];
char scale_type_x[9], scale_type_y[9];
float scale_x, scale_y;
};
typedef struct glslp_t {
char name[64];
int num_shaders;
struct shader shaders[MAX_SHADERS];
int num_textures;
struct texture textures[MAX_TEXTURES];
int num_parameters;
struct parameter parameters[MAX_PARAMETERS];
int input_filter_linear;
} glslp_t;
void get_glslp_name(const char *f, char *s, int size);
glslp_t *glslp_parse(const char *f);
void glslp_free(glslp_t *p);
void glslp_read_shader_config(glslp_t *shader);
void glslp_write_shader_config(glslp_t *shader);
#endif /* SRC_WX_GLSLP_PARSER_H_ */

View File

@@ -52,7 +52,12 @@ extern uint8_t rom_read(uint32_t addr, void *priv);
extern uint16_t rom_readw(uint32_t addr, void *priv);
extern uint32_t rom_readl(uint32_t addr, void *priv);
extern void rom_write(uint32_t addr, uint8_t val, void *priv);
extern void rom_writew(uint32_t addr, uint16_t val, void *priv);
extern void rom_writel(uint32_t addr, uint32_t val, void *priv);
extern void rom_get_full_path(char *dest, const char *fn);
extern FILE *rom_fopen(const char *fn, char *mode);
extern int rom_getfile(char *fn, char *s, int size);
extern int rom_present(const char *fn);

View File

@@ -54,18 +54,24 @@ typedef struct scsi_cdrom_t {
int do_page_save;
int unit_attention;
int request_pos;
int old_len;
int media_status;
int wait;
int buffer_pos;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;
int is_sony;
int use_cdb_9;
uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen);
int use_cdb_9;
int was_cached;
int toc_cached;
int media_access;
uint8_t vendor_type;
uint8_t ven_cmd_is_data[256];
mode_sense_pages_t ms_drive_status_pages_saved;
@@ -74,8 +80,6 @@ typedef struct scsi_cdrom_t {
mode_sense_pages_t ms_pages_default;
mode_sense_pages_t ms_pages_changeable;
uint8_t (*ven_cmd)(void *sc, const uint8_t *cdb, int32_t *BufLen);
} scsi_cdrom_t;
#endif

View File

@@ -110,39 +110,40 @@
#define GPCMD_MECHANISM_STATUS 0xbd
#define GPCMD_READ_CD 0xbe
#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */
#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */
#define GPCMD_AUDIO_TRACK_SEARCH_TOSHIBA 0xc0 /* Toshiba Vendor Unique command */
#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */
#define GPCMD_EJECT_CHINON 0xc0 /* Chinon Vendor Unique command */
#define GPCMD_MAGAZINE_EJECT_PIONEER 0xc0 /* Pioneer Vendor Unique command */
#define GPCMD_SET_ADDRESS_FORMAT_SONY 0xc0 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TOSHIBA 0xc1 /* Toshiba Vendor Unique command */
#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */
#define GPCMD_READ_TOC_PIONEER 0xc1 /* Pioneer Vendor Unique command */
#define GPCMD_READ_TOC_SONY 0xc1 /* Sony Vendor Unique command */
#define GPCMD_PAUSE_RESUME_ALT 0xc2
#define GPCMD_READ_SUBCHANNEL_MATSUSHITA 0xc2 /* Matsushita Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */
#define GPCMD_READ_SUBCHANNEL_SONY 0xc2 /* Sony Vendor Unique command */
#define GPCMD_STILL_TOSHIBA 0xc2 /* Toshiba Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PIONEER 0xc2 /* Pioneer Vendor Unique command */
#define GPCMD_READ_TOC_MATSUSHITA 0xc3 /* Matsushita Vendor Unique command */
#define GPCMD_READ_HEADER_SONY 0xc3 /* Sony Vendor Unique command */
#define GPCMD_SET_STOP_TIME_TOSHIBA 0xc3 /* Toshiba Vendor Unique command */
#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */
#define GPCMD_CADDY_EJECT_TOSHIBA 0xc4 /* Toshiba Vendor Unique command */
#define GPCMD_PLAYBACK_STATUS_SONY 0xc4 /* Sony Vendor Unique command */
#define GPCMD_READ_HEADER_MATSUSHITA 0xc4 /* Matsushita Vendor Unique command */
#define GPCMD_PAUSE_SONY 0xc5 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MATSUSHITA 0xc5 /* Matsushita Vendor Unique command */
#define GPCMD_UNKNOWN_SCSI2_NEC 0xc5 /* NEC Vendor Unique Command */
#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */
#define GPCMD_PLAY_TRACK_SONY 0xc6 /* Sony Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_TOSHIBA 0xc6 /* Toshiba Vendor Unique command */
#define GPCMD_STOP_CHINON 0xc6 /* Chinon Vendor Unique command */
#define GPCMD_PLAY_AUDIO_MSF_MATSUSHITA 0xc7 /* Matsushita Vendor Unique command*/
#define GPCMD_PLAY_MSF_SONY 0xc7 /* Sony Vendor Unique command*/
#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */
#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */
#define GPCMD_AUDIO_TRACK_SEARCH_PIONEER 0xc8 /* Pioneer Vendor Unique command */
#define GPCMD_PLAY_AUDIO_SONY 0xc8 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_INDEX_MATSUSHITA 0xc8 /* Matsushita Vendor Unique command */
#define GPCMD_READ_CDROM_MODE_TOSHIBA 0xc8 /* Toshiba Vendor Unique command */
#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_10_MATSUSHITA 0xc9 /* Matsushita Vendor Unique command */
#define GPCMD_PLAYBACK_CONTROL_SONY 0xc9 /* Sony Vendor Unique command */
#define GPCMD_PLAY_AUDIO_PIONEER 0xc9 /* Pioneer Vendor Unique command */
#define GPCMD_PAUSE_PIONEER 0xca /* Pioneer Vendor Unique command */
#define GPCMD_PAUSE_RESUME_MATSUSHITA 0xcb /* Matsushita Vendor Unique command */
#define GPCMD_STOP_PIONEER 0xcb /* Pioneer Vendor Unique command */
@@ -151,8 +152,8 @@
#define GPCMD_READ_CD_MSF_OLD 0xd5 /* Should be equivalent to 0xb9 */
#define GPCMD_AUDIO_TRACK_SEARCH_NEC 0xd8 /* NEC Vendor Unique command */
#define GPCMD_PLAY_AUDIO_NEC 0xd9 /* NEC Vendor Unique command */
#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */
#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */
#define GPCMD_STILL_NEC 0xda /* NEC Vendor Unique command */
#define GPCMD_SET_STOP_TIME_NEC 0xdb /* NEC Vendor Unique command */
#define GPCMD_CADDY_EJECT_NEC 0xdc /* NEC Vendor Unique command */
#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC 0xdd /* NEC Vendor Unique command */
@@ -409,12 +410,13 @@ typedef struct scsi_common_s {
int do_page_save;
int unit_attention;
int request_pos;
int old_len;
int media_status;
int wait;
int buffer_pos;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -53,6 +53,7 @@ typedef struct scsi_disk_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -47,13 +47,12 @@ typedef struct ega_t {
uint8_t ctl_mode;
uint8_t color_mux;
uint8_t dot;
uint8_t crtc[32];
uint8_t gdcreg[16];
uint8_t crtc[256];
uint8_t gdcreg[256];
uint8_t attrregs[32];
uint8_t seqregs[64];
uint8_t egapal[16];
uint8_t regs[256];
uint8_t *vram;
uint16_t light_pen;
@@ -73,6 +72,7 @@ typedef struct ega_t {
int oddeven_page;
int oddeven_chain;
int vc;
int real_vc;
int sc;
int dispon;
int hdisp_on;
@@ -113,6 +113,9 @@ typedef struct ega_t {
int remap_required;
int actual_type;
int chipset;
int mono_display;
int mdacols[256][2][2];
uint32_t charseta;
uint32_t charsetb;
@@ -140,6 +143,11 @@ typedef struct ega_t {
uint32_t (*remap_func)(struct ega_t *ega, uint32_t in_addr);
void (*render)(struct ega_t *svga);
/*If set then another device is driving the monitor output and the EGA
card should not attempt to display anything */
void (*render_override)(void *priv);
void *priv_parent;
} ega_t;
#endif
@@ -150,6 +158,7 @@ extern const device_t sega_device;
extern const device_t atiega800p_device;
extern const device_t iskra_ega_device;
extern const device_t et2000_device;
extern const device_t jega_device;
#endif
extern int update_overscan;
@@ -172,6 +181,7 @@ extern uint8_t ega_in(uint16_t addr, void *priv);
extern void ega_poll(void *priv);
extern void ega_write(uint32_t addr, uint8_t val, void *priv);
extern uint8_t ega_read(uint32_t addr, void *priv);
extern void ega_set_type(void *priv, uint32_t local);
extern int firstline_draw;
extern int lastline_draw;
@@ -199,4 +209,19 @@ void ega_render_text(ega_t *ega);
void ega_render_graphics(ega_t *ega);
#endif
enum {
EGA_IBM = 0,
EGA_COMPAQ,
EGA_SUPEREGA,
EGA_ATI800P,
EGA_ISKRA,
EGA_TSENG
};
enum {
EGA_TYPE_IBM = 0,
EGA_TYPE_OTHER = 1,
EGA_TYPE_COMPAQ = 2
};
#endif /*VIDEO_EGA_H*/

View File

@@ -456,6 +456,9 @@ extern const device_t millennium_ii_device;
extern const device_t productiva_g100_device;
#endif /* USE_G100 */
/* JEGA */
extern const device_t if386jega_device;
/* Oak OTI-0x7 */
extern const device_t oti037c_device;
extern const device_t oti067_device;

View File

@@ -108,6 +108,7 @@ typedef struct zip_t {
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
uint32_t block_len;
double callback;

View File

@@ -28,6 +28,7 @@
#include <86box/io.h>
#include <86box/timer.h>
#include "cpu.h"
#include "x86.h"
#include <86box/m_amstrad.h>
#include <86box/pci.h>
@@ -344,6 +345,8 @@ inb(uint16_t port)
int qfound = 0;
#endif
io_port = port;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif
@@ -408,6 +411,9 @@ outb(uint16_t port, uint8_t val)
int qfound = 0;
#endif
io_port = port;
io_val = val;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif
@@ -464,6 +470,8 @@ inw(uint16_t port)
#endif
uint8_t ret8[2];
io_port = port;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif
@@ -540,6 +548,9 @@ outw(uint16_t port, uint16_t val)
int qfound = 0;
#endif
io_port = port;
io_val = val;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif
@@ -612,6 +623,8 @@ inl(uint16_t port)
int qfound = 0;
#endif
io_port = port;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif
@@ -720,6 +733,9 @@ outl(uint16_t port, uint32_t val)
#endif
int i = 0;
io_port = port;
io_val = val;
#ifdef USE_DEBUG_REGS_486
io_debug_check_addr(port);
#endif

View File

@@ -641,6 +641,31 @@ machine_at_cmdsl386sx16_init(const machine_t *model)
return ret;
}
int
machine_at_if386sx_init(const machine_t *model)
{
int ret;
ret = bios_load_interleaved("roms/machines/if386sx/OKI_IF386SX_odd.bin",
"roms/machines/if386sx/OKI_IF386SX_even.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&keyboard_at_phoenix_device);
device_add(&neat_sx_device);
device_add(&if386jega_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
return ret;
}
static void
machine_at_scamp_common_init(const machine_t *model, int is_ps2)
{
@@ -750,9 +775,6 @@ machine_at_acer100t_init(const machine_t *model)
machine_at_ps2_ide_init(model);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&ali1409_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&oti077_acer100t_device);

View File

@@ -541,3 +541,31 @@ machine_at_6via90ap_init(const machine_t *model)
return ret;
}
int
machine_at_7sbb_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/7sbb/sbb12aa2.bin",
0x000c0000, 262144, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x10, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0);
device_add(&sis_5600_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&it8661f_device);
device_add(&sst_flash_29ee020_device); /* assumed */
return ret;
}

View File

@@ -366,7 +366,11 @@ machine_xt_init(const machine_t *model)
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1);
(void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0);
/* On the real machine, the BASIC is repeated. */
(void) bios_load_aux_linear(fn, 0x000f0000, 8192, 0);
(void) bios_load_aux_linear(fn, 0x000f2000, 8192, 0);
(void) bios_load_aux_linear(fn, 0x000f4000, 8192, 0);
(void) bios_load_aux_linear(fn, 0x000f6000, 8192, 0);
}
device_context_restore();

View File

@@ -115,7 +115,9 @@ const machine_filter_t machine_chipsets[] = {
{ "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V },
{ "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II },
{ "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT },
{ "C&T CS8121 NEAT", MACHINE_CHIPSET_NEAT },
{ "C&T 82C236 SCATsx", MACHINE_CHIPSET_SCAT_SX },
{ "C&T CS8221 NEAT", MACHINE_CHIPSET_NEAT },
{ "C&T CS8281 NEATsx", MACHINE_CHIPSET_NEAT_SX },
{ "C&T 386", MACHINE_CHIPSET_CT_386 },
{ "C&T CS4031", MACHINE_CHIPSET_CT_CS4031 },
{ "Contaq 82C596", MACHINE_CHIPSET_CONTAQ_82C596 },
@@ -1760,7 +1762,7 @@ const machine_t machines[] = {
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_8088,
.package = CPU_PKG_8088_VTECH,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
@@ -2623,7 +2625,7 @@ const machine_t machines[] = {
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_8086,
.package = CPU_PKG_8086_VTECH,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
@@ -2758,9 +2760,9 @@ const machine_t machines[] = {
.bus_flags = MACHINE_PS2,
.flags = MACHINE_XTA | MACHINE_VIDEO_FIXED,
.ram = {
.min = 1024,
.min = 512,
.max = 16384,
.step = 1024
.step = 512
},
.nvrmask = 127,
.kbc_device = NULL,
@@ -4746,6 +4748,44 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
{ .name = "[NEATsx] OKI if386AX30L",
.internal_name = "if386sx",
.type = MACHINE_TYPE_386SX,
.chipset = MACHINE_CHIPSET_NEAT_SX,
.init = machine_at_if386sx_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386SX,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_VIDEO_FIXED,
.ram = {
.min = 1024,
.max = 4096,
.step = 1024
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM AT KBC firmware. */
{
.name = "[OPTi 291] DTK PPM-3333P",
@@ -4913,10 +4953,10 @@ const machine_t machines[] = {
/* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a
photo or real hardware BIOS string is found. */
{
.name = "[SCAT] Kaimei KMX-C-02",
.name = "[SCATsx] Kaimei KMX-C-02",
.internal_name = "kmxc02",
.type = MACHINE_TYPE_386SX,
.chipset = MACHINE_CHIPSET_SCAT,
.chipset = MACHINE_CHIPSET_SCAT_SX,
.init = machine_at_kmxc02_init,
.p1_handler = NULL,
.gpio_handler = NULL,
@@ -8862,7 +8902,7 @@ const machine_t machines[] = {
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PCI,
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_VIDEO | MACHINE_SOUND | MACHINE_APM,
.ram = {
.min = 1024,
@@ -9318,7 +9358,7 @@ const machine_t machines[] = {
.min_multi = MACHINE_MULTIPLIER_FIXED,
.max_multi = MACHINE_MULTIPLIER_FIXED
},
.bus_flags = MACHINE_PCI,
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE | MACHINE_APM,
.ram = {
.min = 2048,
@@ -16227,6 +16267,48 @@ const machine_t machines[] = {
.snd_device = &cmi8738_onboard_device,
.net_device = NULL
},
/* SiS (5)600 */
/* Has the SiS 600 chipset, which is a re-brand of the 5600, with
on-chip KBC. */
{
.name = "[SiS 600] Soyo SY-7SBB",
.internal_name = "7sbb",
.type = MACHINE_TYPE_SOCKET370,
.chipset = MACHINE_CHIPSET_SIS_5600,
.init = machine_at_7sbb_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET370,
.block = CPU_BLOCK(CPU_CYRIX3S),
.min_bus = 60000000,
.max_bus = 100000000,
.min_voltage = 1800,
.max_voltage = 3500,
.min_multi = 1.5,
.max_multi = 8.0
},
.bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB,
.flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB,
.ram = {
.min = 8192,
.max = 1572864,
.step = 1024
},
.nvrmask = 255,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Miscellaneous/Fake/Hypervisor machines */
/* Has a Winbond W83977F Super I/O chip with on-chip KBC with AMIKey-2 KBC

View File

@@ -225,6 +225,21 @@ flushmmucache(void)
#endif
}
void
flushmmucache_write(void)
{
for (uint16_t c = 0; c < 256; c++) {
if (writelookup[c] != (int) 0xffffffff) {
page_lookup[writelookup[c]] = NULL;
page_lookupp[writelookup[c]] = 4;
writelookup2[writelookup[c]] = LOOKUP_INV;
writelookupp[writelookup[c]] = 4;
writelookup[c] = 0xffffffff;
}
}
mmuflush++;
}
void
flushmmucache_pc(void)
{
@@ -1518,10 +1533,28 @@ readmemql(uint32_t addr)
addr = addr64a[0] & rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_l)
return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32);
return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32);
if (map && map->read_l)
return map->read_l(addr, map->priv) |
((uint64_t) map->read_l(addr + 4, map->priv) << 32);
if (map && map->read_w)
return map->read_w(addr, map->priv) |
((uint64_t) map->read_w(addr + 2, map->priv) << 16) |
((uint64_t) map->read_w(addr + 4, map->priv) << 32) |
((uint64_t) map->read_w(addr + 6, map->priv) << 48);
if (map && map->read_b)
return map->read_b(addr, map->priv) |
((uint64_t) map->read_b(addr + 1, map->priv) << 8) |
((uint64_t) map->read_b(addr + 2, map->priv) << 16) |
((uint64_t) map->read_b(addr + 3, map->priv) << 24) |
((uint64_t) map->read_b(addr + 4, map->priv) << 32) |
((uint64_t) map->read_b(addr + 5, map->priv) << 40) |
((uint64_t) map->read_b(addr + 6, map->priv) << 48) |
((uint64_t) map->read_b(addr + 7, map->priv) << 56);
return 0xffffffffffffffffULL;
}
void
@@ -2370,7 +2403,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size)
for (i_c = i_s; i_c <= i_e; i_c += i_a) {
for (c = (start + i_c); c < (end + i_c); c += MEM_GRANULARITY_SIZE) {
/* CPU */
n = !!in_smm;
n = (!!in_smm) || (is_cxsmm && (ccr1 & CCR1_SMAC));
wp = _mem_wp[c >> MEM_GRANULARITY_BITS];
if (map->exec && mem_mapping_access_allowed(map->flags,

View File

@@ -102,8 +102,8 @@ mem_readw_map(uint32_t addr)
if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w))
ret = map->read_w(addr, map->priv);
else {
ret = mem_readb_phys(addr + 1) << 8;
ret |= mem_readb_phys(addr);
ret = mem_readb_map(addr);
ret |= ((uint16_t) mem_readb_map(addr + 1)) << 8;
}
return ret;
@@ -120,8 +120,8 @@ mem_readl_map(uint32_t addr)
if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l))
ret = map->read_l(addr, map->priv);
else {
ret = mem_readw_phys(addr + 2) << 16;
ret |= mem_readw_phys(addr);
ret = mem_readw_map(addr);
ret |= ((uint32_t) mem_readw_map(addr + 2)) << 16;
}
return ret;
@@ -148,8 +148,8 @@ mem_writew_map(uint32_t addr, uint16_t val)
if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w))
map->write_w(addr, val, map->priv);
else {
mem_writeb_phys(addr, val & 0xff);
mem_writeb_phys(addr + 1, val >> 8);
mem_writeb_map(addr, val & 0xff);
mem_writeb_map(addr + 1, val >> 8);
}
}
@@ -161,10 +161,10 @@ mem_writel_map(uint32_t addr, uint32_t val)
mem_logical_addr = 0xffffffff;
if (!cpu_16bitbus && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l))
map->write_l(addr, val, map->priv);
map->write_l(addr, val, map->priv);
else {
mem_writew_phys(addr, val & 0xffff);
mem_writew_phys(addr + 2, val >> 16);
mem_writew_map(addr, val & 0xffff);
mem_writew_map(addr + 2, val >> 16);
}
}
@@ -649,7 +649,7 @@ readmemll_2386(uint32_t addr)
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
return readmemwl_no_mmut_2386(addr, addr64a) |
(((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16);
(((uint32_t) readmemwl_no_mmut_2386(addr + 2, &(addr64a[2]))) << 16);
}
}
@@ -925,10 +925,28 @@ readmemql_2386(uint32_t addr)
addr = addr64a[0] & rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_l)
return map->read_l(addr, map->priv) | ((uint64_t) map->read_l(addr + 4, map->priv) << 32);
return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32);
if (map && map->read_l)
return map->read_l(addr, map->priv) |
((uint64_t) map->read_l(addr + 4, map->priv) << 32);
if (map && map->read_w)
return map->read_w(addr, map->priv) |
((uint64_t) map->read_w(addr + 2, map->priv) << 16) |
((uint64_t) map->read_w(addr + 4, map->priv) << 32) |
((uint64_t) map->read_w(addr + 6, map->priv) << 48);
if (map && map->read_b)
return map->read_b(addr, map->priv) |
((uint64_t) map->read_b(addr + 1, map->priv) << 8) |
((uint64_t) map->read_b(addr + 2, map->priv) << 16) |
((uint64_t) map->read_b(addr + 3, map->priv) << 24) |
((uint64_t) map->read_b(addr + 4, map->priv) << 32) |
((uint64_t) map->read_b(addr + 5, map->priv) << 40) |
((uint64_t) map->read_b(addr + 6, map->priv) << 48) |
((uint64_t) map->read_b(addr + 7, map->priv) << 56);
return 0xffffffffffffffffULL;
}
void

View File

@@ -244,6 +244,57 @@ rom_readl(uint32_t addr, void *priv)
return (*(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask]);
}
void
rom_write(uint32_t addr, uint8_t val, void *priv)
{
const rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: write byte from BIOS at %06lX\n", addr);
#endif
if (addr < rom->mapping.base)
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
void
rom_writew(uint32_t addr, uint16_t val, void *priv)
{
rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: write word from BIOS at %06lX\n", addr);
#endif
if (addr < (rom->mapping.base - 1))
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
*(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
void
rom_writel(uint32_t addr, uint32_t val, void *priv)
{
rom_t *rom = (rom_t *) priv;
#ifdef ROM_TRACE
if (rom->mapping.base == ROM_TRACE)
rom_log("ROM: write long from BIOS at %06lX\n", addr);
#endif
if (addr < (rom->mapping.base - 3))
return;
if (addr >= (rom->mapping.base + rom->sz))
return;
*(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val;
}
int
rom_load_linear_oddeven(const char *fn, uint32_t addr, int sz, int off, uint8_t *ptr)
{

View File

@@ -1177,9 +1177,15 @@ modem_process_telnet(modem_t *modem, uint8_t *data, uint32_t size)
uint8_t c = data[i];
if (modem->telClient.inIAC) {
if (modem->telClient.recCommand) {
modem_log("modem_process_telnet: received command %i, option %i\n", modem->telClient.command, c);
if ((c != 0) && (c != 1) && (c != 3)) {
if (modem->telClient.command > 250) {
/* Reject anything we don't recognize */
/* Reject anything we don't recognize */
if (modem->telClient.command == 251 || modem->telClient.command == 252) {
modem_data_mode_process_byte(modem, 0xff);
modem_data_mode_process_byte(modem, 254);
modem_data_mode_process_byte(modem, c); /* Don't do crap! */
} else if (modem->telClient.command == 253 || modem->telClient.command == 254) {
modem_data_mode_process_byte(modem, 0xff);
modem_data_mode_process_byte(modem, 252);
modem_data_mode_process_byte(modem, c); /* We won't do crap! */

View File

@@ -155,14 +155,22 @@ net_slirp_timer_mod(void *timer, int64_t expire_timer, UNUSED(void *opaque))
}
static void
#if SLIRP_CHECK_VERSION(4, 9, 0)
net_slirp_register_poll_socket(slirp_os_socket fd, void *opaque)
#else
net_slirp_register_poll_fd(int fd, void *opaque)
#endif
{
(void) fd;
(void) opaque;
}
static void
#if SLIRP_CHECK_VERSION(4, 9, 0)
net_slirp_unregister_poll_socket(slirp_os_socket fd, void *opaque)
#else
net_slirp_unregister_poll_fd(int fd, void *opaque)
#endif
{
(void) fd;
(void) opaque;
@@ -198,7 +206,11 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque)
#ifdef _WIN32
static int
# if SLIRP_CHECK_VERSION(4, 9, 0)
net_slirp_add_poll(slirp_os_socket fd, int events, void *opaque)
# else
net_slirp_add_poll(int fd, int events, void *opaque)
# endif
{
net_slirp_t *slirp = (net_slirp_t *) opaque;
long bitmask = 0;
@@ -216,7 +228,11 @@ net_slirp_add_poll(int fd, int events, void *opaque)
}
#else
static int
# if SLIRP_CHECK_VERSION(4, 9, 0)
net_slirp_add_poll(slirp_os_socket fd, int events, void *opaque)
# else
net_slirp_add_poll(int fd, int events, void *opaque)
# endif
{
net_slirp_t *slirp = (net_slirp_t *) opaque;
@@ -307,8 +323,13 @@ static const SlirpCb slirp_cb = {
.timer_new = net_slirp_timer_new,
.timer_free = net_slirp_timer_free,
.timer_mod = net_slirp_timer_mod,
#if SLIRP_CHECK_VERSION(4, 9, 0)
.register_poll_socket = net_slirp_register_poll_socket,
.unregister_poll_socket = net_slirp_unregister_poll_socket,
#else
.register_poll_fd = net_slirp_register_poll_fd,
.unregister_poll_fd = net_slirp_unregister_poll_fd,
#endif
.notify = net_slirp_notify
};
@@ -362,7 +383,11 @@ net_slirp_thread(void *priv)
bool run = true;
while (run) {
uint32_t timeout = -1;
# if SLIRP_CHECK_VERSION(4, 9, 0)
slirp_pollfds_fill_socket(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
# else
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
# endif
if (timeout < 0)
timeout = INFINITE;
@@ -409,7 +434,11 @@ net_slirp_thread(void *priv)
net_slirp_add_poll(net_event_get_fd(&slirp->stop_event), SLIRP_POLL_IN, slirp);
net_slirp_add_poll(net_event_get_fd(&slirp->tx_event), SLIRP_POLL_IN, slirp);
# if SLIRP_CHECK_VERSION(4, 9, 0)
slirp_pollfds_fill_socket(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
# else
slirp_pollfds_fill(slirp->slirp, &timeout, net_slirp_add_poll, slirp);
# endif
int ret = poll(slirp->pfd, slirp->pfd_len, timeout);
@@ -460,10 +489,47 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv
struct in_addr dhcp = { .s_addr = htonl(0x0a00000f | (slirp_card_num << 8)) }; /* 10.0.x.15 */
struct in_addr dns = { .s_addr = htonl(0x0a000003 | (slirp_card_num << 8)) }; /* 10.0.x.3 */
struct in_addr bind = { .s_addr = htonl(0x00000000) }; /* 0.0.0.0 */
struct in6_addr ipv6_dummy = { 0 }; /* contents don't matter; we're not using IPv6 */
const SlirpConfig slirp_config = {
#if SLIRP_CHECK_VERSION(4, 9, 0)
.version = 6,
#else
.version = 1,
#endif
.restricted = 0,
.in_enabled = 1,
.vnetwork = net,
.vnetmask = mask,
.vhost = host,
.in6_enabled = 0,
.vprefix_addr6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, /* fec0:: - unused */
.vprefix_len = 64,
.vhost6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02 } }, /* fec0::2 - unused */
.vhostname = "86Box",
.tftp_server_name = NULL,
.tftp_path = NULL,
.bootfile = NULL,
.vdhcp_start = dhcp,
.vnameserver = dns,
.vnameserver6 = { .s6_addr = { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03 } }, /* fec0::3 - unused */
.vdnssearch = NULL,
.vdomainname = NULL,
.if_mtu = 0,
.if_mru = 0,
.disable_host_loopback = 0,
.enable_emu = 0,
#if SLIRP_CHECK_VERSION(4, 9, 0)
.outbound_addr = NULL,
.outbound_addr6 = NULL,
.disable_dns = 0,
.disable_dhcp = 0,
.mfr_id = 0,
.oob_eth_addr = { 0, 0, 0, 0, 0, 0 }
#endif
};
/* Initialize SLiRP. */
slirp->slirp = slirp_init(0, 1, net, mask, host, 0, ipv6_dummy, 0, ipv6_dummy, NULL, NULL, NULL, NULL, dhcp, dns, ipv6_dummy, NULL, NULL, &slirp_cb, slirp);
slirp->slirp = slirp_new(&slirp_config, &slirp_cb, slirp);
if (!slirp->slirp) {
slirp_log("SLiRP: initialization failed\n");
snprintf(netdrv_errbuf, NET_DRV_ERRBUF_SIZE, "SLiRP initialization failed");

View File

@@ -971,7 +971,8 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque)
case CSR(7):
s->csr[7] = data;
tulip_update_int(s);
if (s->device_info->local)
tulip_update_int(s);
break;
case CSR(8):
@@ -1006,7 +1007,7 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque)
case CSR(13):
s->csr[13] = data;
if (s->device_info->local == 3 && (data & 0x4)) {
if ((s->device_info->local == 3) && (data & 0x4)) {
s->csr[13] = 0x8f01;
s->csr[14] = 0xfffd;
s->csr[15] = 0;
@@ -1407,7 +1408,7 @@ nic_init(const device_t *info)
if (!s)
return NULL;
if (info->local && info->local != 3) {
if (info->local && (info->local != 3)) {
s->bios_addr = 0xD0000;
s->has_bios = device_get_config_int("bios");
} else {
@@ -1434,7 +1435,7 @@ nic_init(const device_t *info)
s->eeprom_data[2] = 0x14;
s->eeprom_data[3] = 0x21;
} else {
/*Subsystem Vendor ID*/
/*Subsystem Vendor ID*/
s->eeprom_data[0] = info->local ? 0x25 : 0x11;
s->eeprom_data[1] = 0x10;
@@ -1549,23 +1550,40 @@ nic_init(const device_t *info)
/*Block Count*/
s->eeprom_data[32] = 0x01;
/*Extended Format - Block Type 2 for 21142/21143*/
/*Extended Format - Block Type 3 for 21142/21143*/
/*Length (0:6) and Format Indicator (7)*/
s->eeprom_data[33] = 0x86;
s->eeprom_data[33] = 0x8d;
/*Block Type*/
s->eeprom_data[34] = 0x02;
s->eeprom_data[34] = 0x03;
/*Media Code (0:5), EXT (6), Reserved (7)*/
s->eeprom_data[35] = 0x01;
/*PHY Number*/
s->eeprom_data[35] = 0x00;
/*General Purpose Control*/
s->eeprom_data[36] = 0xff;
s->eeprom_data[37] = 0xff;
/*GPR Length*/
s->eeprom_data[36] = 0x00;
/*General Purpose Data*/
/*Reset Length*/
s->eeprom_data[37] = 0x00;
/*Media Capabilities*/
s->eeprom_data[38] = 0x00;
s->eeprom_data[39] = 0x00;
s->eeprom_data[39] = 0x78;
/*Nway Advertisement*/
s->eeprom_data[40] = 0xe0;
s->eeprom_data[41] = 0x01;
/*FDX Bit Map*/
s->eeprom_data[42] = 0x00;
s->eeprom_data[43] = 0x50;
/*TTM Bit Map*/
s->eeprom_data[44] = 0x00;
s->eeprom_data[45] = 0x18;
/*MII PHY Insertion/removal Indication*/
s->eeprom_data[46] = 0x00;
}
s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff;
@@ -1608,7 +1626,7 @@ nic_init(const device_t *info)
checksum *= 2;
if (checksum > 65535)
checksum = checksum % 65535;
/* 3rd pair. */
checksum += (s->eeprom_data[4] * 256) | s->eeprom_data[5];
if (checksum > 65535)
@@ -1616,7 +1634,7 @@ nic_init(const device_t *info)
if (checksum >= 65535)
checksum = 0;
s->eeprom_data[6] = (checksum >> 8) & 0xFF;
s->eeprom_data[7] = checksum & 0xFF;
}

View File

@@ -89,11 +89,7 @@ add_library(ui STATIC
qt_hardwarerenderer.hpp
qt_openglrenderer.cpp
qt_openglrenderer.hpp
qt_opengloptions.cpp
qt_opengloptions.hpp
qt_opengloptionsdialog.cpp
qt_opengloptionsdialog.hpp
qt_opengloptionsdialog.ui
qt_glsl_parser.cpp
qt_settings.cpp
qt_settings.hpp
@@ -190,6 +186,14 @@ add_library(ui STATIC
../qt_resources.qrc
./qdarkstyle/dark/darkstyle.qrc
qt_openglshadermanagerdialog.hpp
qt_openglshadermanagerdialog.cpp
qt_openglshadermanagerdialog.ui
qt_openglshaderconfig.hpp
qt_openglshaderconfig.cpp
qt_openglshaderconfig.ui
)
if(RTMIDI)

View File

@@ -2141,3 +2141,6 @@ msgstr ""
msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer."
msgstr ""
msgid "Inhibit multimedia keys on Windows"
msgstr ""

View File

@@ -37,7 +37,7 @@ msgid "&Hide status bar"
msgstr "&Masquer la barre de status"
msgid "Hide &toolbar"
msgstr "Hide &toolbar"
msgstr "Masquer la &barre d'outils"
msgid "&Resizeable window"
msgstr "Fenètre &Retaillable"

View File

@@ -868,7 +868,7 @@ msgid "Hardware not available"
msgstr "ハードウェアが利用できません"
msgid "Make sure %1 is installed and that you are on a %1-compatible network connection."
msgstr "がインストールされてるか、%1に対応したネットワークに接続されてるか確認してください。"
msgstr "%1がインストールされていてかつ、%1に対応したネットワークに接続されてるか確認してください。"
msgid "Invalid configuration"
msgstr "不正な設定です"
@@ -910,10 +910,10 @@ msgid "OpenGL options"
msgstr "OpenGL設定"
msgid "You are loading an unsupported configuration"
msgstr "読み込んでいる設定がサポートされません"
msgstr "サポートされていないコンフィグを読み込んでいます"
msgid "CPU type filtering based on selected machine is disabled for this emulated machine.\n\nThis makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software.\n\nEnabling this setting is not officially supported and any bug reports filed may be closed as invalid."
msgstr "選択したマシンに基づくCPUタイプのフィルター機能は、使用中のマシンでは無効になっています。\n\nこれにより、選択したマシンと互換性のないCPUが選択できます。しかし、マシンのBIOSや他のソフトウェアと互換性がない場合があります。\n\nこの設定を有効にすることは公式にはサポートされておらず、バグレポートは無効として中止される可能性があります。"
msgstr "選択したマシンに基づくCPUタイプのフィルター機能は、使用中のマシンでは無効になっています。\n\nこれにより、選択したマシンと互換性のないCPUが選択できます。しかし、マシンのBIOSや他のソフトウェアと互換性がない場合があります。\n\nこの設定を有効にすることは公式にはサポートされておらず、バグレポートは無効としてクローズされる可能性があります。"
msgid "Continue"
msgstr "続行"
@@ -1015,7 +1015,7 @@ msgid "The selected file will be overwritten. Are you sure you want to use it?"
msgstr "選択したファイルは上書きされます。よろしいですか?"
msgid "Unsupported disk image"
msgstr "非対応のディスクイメージ"
msgstr "非対応のディスクイメージ"
msgid "Overwrite"
msgstr "上書き"
@@ -1285,7 +1285,7 @@ msgid "Host CD/DVD Drive (%1)"
msgstr "ホスト CD/DVD ドライブ (%1)"
msgid "Unknown Bus"
msgstr "不明バス"
msgstr "不明バス"
msgid "Null Driver"
msgstr "ヌル・ドライバー"
@@ -1294,7 +1294,7 @@ msgid "NIC %02i (%ls) %ls"
msgstr "NIC %02i (%ls) %ls"
msgid "Error opening \"%1\": %2"
msgstr "エラー・オープニング\"%1\": %2"
msgstr "\"%1\"を開く際にエラーが発生しました: %2"
msgid "Error compiling vertex shader in file \"%1\""
msgstr "ファイル\"%1\"の頂点シェーダのコンパイルエラー。"

View File

@@ -682,10 +682,10 @@ msgid "Surface images"
msgstr "Ảnh bề mặt"
msgid "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."
msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/machines. Hãy chọn mẫu máy khác."
msgstr "Mẫu máy \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/machines. Hãy chọn mẫu máy khác."
msgid "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card."
msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Hãy chọn card đồ họa khác."
msgstr "Card đồ họa \"%hs\" không giả lập được do thiếu file ROM tương ứng trong thư mục roms/video. Hãy chọn card đồ họa khác."
msgid "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card."
msgstr "Card đồ họa 2 \"%hs\" không giả lập được do thiếu file ROM tương ứng trong mục roms/video. Vô hiệu hóa card đồ họa thứ hai."
@@ -1219,7 +1219,7 @@ msgid "Development of the WinBox manager stopped in 2022 due to a lack of mainta
msgstr "Trình quản lý phiên WinBox đã bị dừng phát triển năm 2022 do thiếu nhân sự duy trì. Vì những quyết định để cho 86Box trở nên tốt hơn, chúng tôi đã không còn hỗ trợ trình quản lý WinBox.\n\n Sẽ không có bản cập nhật mới cho WinBox nữa, và nếu bạn tiếp tục sử dụng với các bản 86Box mới hơn có thể gặp lỗi. Bất kì các bản bug report liên quan đến lỗi của WinBox sẽ bị coi là không hợp lệ và bị đóng.\n\nTruy cập 86Box.net để tìm qua các trình quản lý phiên/manager khác cho phù hợp."
msgid "Generate"
msgstr "Phát ra"
msgstr "Tạo"
msgid "Joystick configuration"
msgstr "Cấu hình cần điều khiển"
@@ -1240,7 +1240,7 @@ msgid "List of MCA devices:"
msgstr "Danh sách các thiết bị MCA:"
msgid "Tablet tool"
msgstr "Công cụ máy tính bảng"
msgstr "Công cụ bảng nhập liệu"
msgid "Qt (OpenGL &ES)"
msgstr "QT (OpenGL &ES)"
@@ -1264,19 +1264,19 @@ msgid "Cursor/Puck"
msgstr "Con trỏ/puck"
msgid "Pen"
msgstr "Cái bút"
msgstr "Bút"
msgid "Host CD/DVD Drive (%1:)"
msgstr "Máy chủ CD/DVD ổ đĩa (%1 :)"
msgid "&Connected"
msgstr "& Kết nối"
msgstr "&Đã kết nối"
msgid "Clear image history"
msgstr "Xóa lịch sử ảnh đĩa"
msgid "Create..."
msgstr "Tạo nên..."
msgstr "Tạo..."
msgid "previous image"
msgstr "đĩa trước đó"
@@ -1309,7 +1309,7 @@ msgid "OpenGL 3.0 renderer options"
msgstr "Tùy chọn kết xuất OpenGL 3.0"
msgid "Render behavior"
msgstr "Hiện ra hành vi"
msgstr "Hành vi kết xuất"
msgid "Use target framerate:"
msgstr "Dùng số khung hình mục tiêu:"
@@ -1321,16 +1321,16 @@ msgid "VSync"
msgstr "Vsync"
msgid "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Render each frame immediately, in sync with the emulated display.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;This is the recommended option if the shaders in use don't utilize frametime for animated effects.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgstr "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không sử dụng hình chữ nhật cho các hiệu ứng hoạt hình.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgstr "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Đây là tùy chọn được đề xuất nếu các shader đang sử dụng không tối ưu frametime cho các hiệu ứng động.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgid "Synchronize with video"
msgstr "Đồng bộ hóa với video"
msgstr "Đồng bộ với video"
msgid "Shaders"
msgstr "Shaders"
msgid "Remove"
msgstr "Di dời"
msgstr "Loại bỏ"
msgid "No shader selected"
msgstr "Không có shader được chọn"
@@ -1363,19 +1363,19 @@ msgid "Error initializing OpenGL"
msgstr "Lỗi khởi tạo OpenGL"
msgid "Falling back to software rendering.\n"
msgstr "Rơi trở lại kết xuất phần mềm.\n"
msgstr "Quay trở lại kết xuất phần mềm.\n"
msgid "Allocating memory for unpack buffer failed.\n"
msgstr "Phân bổ bộ nhớ cho bộ đệm giải nén không thành công.\n"
msgid "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When selecting media images (CD-ROM, floppy, etc.) the open dialog will start in the same directory as the 86Box configuration file. This setting will likely only make a difference on macOS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgstr "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Khi chọn hình ảnh phương tiện (CD-ROM, FLOPPY, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgstr "&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Khi chọn hình ảnh phương tiện (CD-ROM, ổ mềm, v.v.), hộp thoại mở sẽ bắt đầu trong cùng thư mục với tệp cấu hình 86box. Cài đặt này có thể sẽ chỉ tạo ra sự khác biệt trên macOS.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;"
msgid "This machine might have been moved or copied."
msgstr "Máy này có thể đã được di chuyển hoặc sao chép."
msgstr "Cấu hình máy này có thể đã được di chuyển hoặc sao chép."
msgid "In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied.\n\nSelect \"I Copied It\" if you are not sure."
msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"."
msgstr "Để đảm bảo chức năng kết nối mạng thích hợp, 86Box cần biết liệu máy này có được di chuyển hay sao chép không.\n\nNếu bạn không chắc chắn, chọn \"Tôi đã sao chép nó\"."
msgid "I Moved It"
msgstr "Tôi đã di chuyển nó"
@@ -1390,7 +1390,7 @@ msgid "No MCA devices."
msgstr "Không có thiết bị MCA."
msgid "MiB"
msgstr "Mib"
msgstr "MiB"
msgid "Network Card #1"
msgstr "Thẻ mạng 1"
@@ -1405,7 +1405,7 @@ msgid "Network Card #4"
msgstr "Thẻ mạng 4"
msgid "Mode"
msgstr "Cách thức"
msgstr "Chế độ"
msgid "Interface"
msgstr "Giao diện"
@@ -1417,7 +1417,7 @@ msgid "VDE Socket"
msgstr "Ổ cắm VDE"
msgid "86Box Unit Tester"
msgstr "Người kiểm tra đơn vị 86box"
msgstr "Trình kiểm tra đơn vị 86box"
msgid "Novell NetWare 2.x Key Card"
msgstr "Thẻ khóa Novell Netware 2.x"
@@ -1435,7 +1435,7 @@ msgid "Serial port passthrough 4"
msgstr "Thông qua cổng serial 4"
msgid "Vision Systems LBA Enhancer"
msgstr "Hệ thống tầm nhìn LBA Enhancer"
msgstr "Vision Systems LBA Enhancer"
msgid "Renderer options..."
msgstr "Tùy chọn kết xuất ..."
@@ -1477,7 +1477,7 @@ msgid "Roland CM-32LN Emulation"
msgstr "Mô phỏng Roland CM-32LN"
msgid "OPL4-ML Daughterboard"
msgstr "Con gái OPL4-ML"
msgstr "Bo mạch con OPL4-ML"
msgid "System MIDI"
msgstr "MIDI của hệ thống"
@@ -1489,7 +1489,7 @@ msgid "BIOS Address"
msgstr "Địa chỉ BIOS"
msgid "Enable BIOS extension ROM Writes"
msgstr "Bật ROM mở rộng BIOS"
msgstr "Kích hoạt ghi ROM mở rộng BIOS"
msgid "Address"
msgstr "Địa chỉ"
@@ -1516,22 +1516,22 @@ msgid "BIOS size"
msgstr "Kích thước BIOS"
msgid "Map C0000-C7FFF as UMB"
msgstr "Bản đồ C0000-C7FFF dưới dạng UMB"
msgstr "Map C0000-C7FFF dưới dạng UMB"
msgid "Map C8000-CFFFF as UMB"
msgstr "Bản đồ C8000-CFFFF dưới dạng UMB"
msgstr "Map C8000-CFFFF dưới dạng UMB"
msgid "Map D0000-D7FFF as UMB"
msgstr "Bản đồ D0000-D7FFF dưới dạng UMB"
msgstr "Map D0000-D7FFF dưới dạng UMB"
msgid "Map D8000-DFFFF as UMB"
msgstr "Bản đồ D8000-Dffff dưới dạng UMB"
msgstr "Map D8000-Dffff dưới dạng UMB"
msgid "Map E0000-E7FFF as UMB"
msgstr "Bản đồ E0000-E7FFF dưới dạng UMB"
msgstr "Map E0000-E7FFF dưới dạng UMB"
msgid "Map E8000-EFFFF as UMB"
msgstr "Bản đồ e8000-effff dưới dạng umb"
msgstr "Map e8000-effff dưới dạng umb"
msgid "JS9 Jumper (JIM)"
msgstr "JS9 Jumper (Jim)"
@@ -1546,13 +1546,13 @@ msgid "MIDI Thru"
msgstr "Thông qua đầu vào MIDI"
msgid "MIDI Clockout"
msgstr "MIDI đồng hồ"
msgstr "MIDI Clockout"
msgid "SoundFont"
msgstr "Soundfont"
msgstr "Font âm thanh"
msgid "Output Gain"
msgstr "Đầu ra tăng"
msgstr "Tăng đầu ra"
msgid "Chorus"
msgstr "Điệp khúc"
@@ -1591,7 +1591,7 @@ msgid "Interpolation Method"
msgstr "Phương pháp nội suy"
msgid "Reverb Output Gain"
msgstr "Gợi ý đầu ra hồi âm"
msgstr "Tăng đầu ra hồi âm"
msgid "Reversed stereo"
msgstr "Đảo ngược âm thanh nổi"
@@ -1612,10 +1612,10 @@ msgid "RTS toggle"
msgstr "RT chuyển đổi"
msgid "Revision"
msgstr "Ôn tập"
msgstr "Bản sửa đổi"
msgid "Controller"
msgstr "Người điều khiển"
msgstr "Bộ điều khiển"
msgid "Show Crosshair"
msgstr "Hiển thị hình chữ thập"
@@ -1627,7 +1627,7 @@ msgid "MAC Address"
msgstr "Địa chỉ MAC"
msgid "MAC Address OUI"
msgstr " OUI địa chỉ MAC"
msgstr "OUI địa chỉ MAC"
msgid "Enable BIOS"
msgstr "Bật BIOS"
@@ -1699,7 +1699,7 @@ msgid "Enable OPL"
msgstr "Bật OPL"
msgid "Receive MIDI input (MPU-401)"
msgstr "Nhận nhập MIDI (MPU-401)"
msgstr "Nhận đầu vào MIDI (MPU-401)"
msgid "SB low DMA"
msgstr "SB DMA thấp"
@@ -1711,7 +1711,7 @@ msgid "Enable CMS"
msgstr "Bật CMS"
msgid "Mixer"
msgstr "Máy trộn"
msgstr "Bộ trộn"
msgid "High DMA"
msgstr "DMA cao"
@@ -1747,13 +1747,13 @@ msgid "RGB type"
msgstr "Loại RGB"
msgid "Line doubling type"
msgstr "Dòng nhân đôi"
msgstr "Loại dòng kép"
msgid "Snow emulation"
msgstr "Đun tuyết"
msgstr "Giả lập hiệu ứng tuyết"
msgid "Monitor type"
msgstr "Loại giám sát"
msgstr "Loại màn hình"
msgid "Character set"
msgstr "Bộ ký tự"
@@ -1762,13 +1762,13 @@ msgid "XGA type"
msgstr "Loại XGA"
msgid "Instance"
msgstr "Ví dụ"
msgstr "Bản chạy"
msgid "MMIO Address"
msgstr "Địa chỉ MMIO"
msgid "RAMDAC type"
msgstr "Loại Ramdac"
msgstr "Loại RAMDAC"
msgid "Blend"
msgstr "Trộn"
@@ -1792,13 +1792,13 @@ msgid "Texture memory size"
msgstr "Kích thước bộ nhớ kết cấu"
msgid "Dither subtraction"
msgstr "Phân biệt trừ"
msgstr "Giảm ngân tán"
msgid "Screen Filter"
msgstr "Bộ lọc màn hình"
msgid "Render threads"
msgstr "Kết xuất chủ đề"
msgstr "Luồng kết xuất"
msgid "SLI"
msgstr "SLI"
@@ -1813,13 +1813,13 @@ msgid "I/O Width"
msgstr "Chiều rộng I/O"
msgid "Transfer Speed"
msgstr "Tốc độ chuyển"
msgstr "Tốc độ truyền tải"
msgid "EMS mode"
msgstr "Chế độ EMS"
msgid "Address for > 2 MB"
msgstr "Địa chỉ cho> 2 MB"
msgstr "Địa chỉ cho > 2 MB"
msgid "Frame Address"
msgstr "Địa chỉ khung"
@@ -1834,7 +1834,7 @@ msgid "Always at selected speed"
msgstr "Luôn ở tốc độ đã chọn"
msgid "BIOS setting + Hotkeys (off during POST)"
msgstr "Cài đặt BIOS + phím nóng (TẮT trong bài đăng)"
msgstr "Cài đặt BIOS + phím nóng (TẮT trong POST)"
msgid "64 kB starting from F0000"
msgstr "64 kb bắt đầu từ f0000"
@@ -1861,7 +1861,7 @@ msgid "Non-timed (original)"
msgstr "Không đúng lúc (bản gốc)"
msgid "45 Hz (JMP2 not populated)"
msgstr "45 Hz (JMP2 không dân cư)"
msgstr "45 Hz (JMP2 không phổ cập)"
msgid "Two"
msgstr "Hai"
@@ -1870,10 +1870,10 @@ msgid "Three"
msgstr "Ba"
msgid "Wheel"
msgstr "Bánh xe"
msgstr "Con lăn"
msgid "Five + Wheel"
msgstr "Năm + bánh xe"
msgstr "Năm + con lăn"
msgid "A3 - SMT2 Serial / SMT3(R)V"
msgstr "A3 - SMT2 Serial / SMT3(R)V"
@@ -2008,7 +2008,7 @@ msgid "Color"
msgstr "Màu sắc"
msgid "U.S. English"
msgstr "Tiếng Anh Hoa Kỳ"
msgstr "Tiếng Anh Mỹ"
msgid "Scandinavian"
msgstr "Scandinavia"
@@ -2020,13 +2020,13 @@ msgid "Bochs latest"
msgstr "Bochs mới nhất"
msgid "Mono Non-Interlaced"
msgstr "Đơn sắc không được xen kẽ"
msgstr "Đơn sắc không xen kẽ"
msgid "Color Interlaced"
msgstr "Màu sắc xen kẽ"
msgid "Color Non-Interlaced"
msgstr "Màu sắc không được xen kẽ"
msgstr "Màu sắc không xen kẽ"
msgid "3Dfx Voodoo Graphics"
msgstr "Đồ họa 3Dfx Voodoo"
@@ -2074,7 +2074,7 @@ msgid "Parallel Line Internet Protocol"
msgstr "Parallel Line Internet Protocol"
msgid "Protection Dongle for Savage Quest"
msgstr "Bảo vệ dongle cho Savage Quest"
msgstr "Dongle bảo vệ cho Savage Quest"
msgid "Serial Passthrough Device"
msgstr "Thiết bị thông qua cổng serial"
@@ -2086,7 +2086,7 @@ msgid "Host Serial Device"
msgstr "Thiết bị serial máy chủ"
msgid "Name of pipe"
msgstr "Tên của đường ống"
msgstr "Tên đường ống"
msgid "Data bits"
msgstr "Bit dữ liệu"
@@ -2095,10 +2095,10 @@ msgid "Stop bits"
msgstr "Dừng bit"
msgid "Baud Rate of Passthrough"
msgstr "Tốc độ baud của qua đường"
msgstr "Tốc độ baud của đường thông"
msgid "Named Pipe (Server)"
msgstr "Đường ống được đặt tên (máy chủ)"
msgstr "Đường ống tên (máy chủ)"
msgid "Host Serial Passthrough"
msgstr "Thông qua cổng serial của máy chủ"
@@ -2107,19 +2107,19 @@ msgid "Eject %s"
msgstr "Đẩy đĩa ra %s"
msgid "&Unmute"
msgstr "&Không quay được"
msgstr "&Mở tiếng"
msgid "Softfloat FPU"
msgstr "Softfloat FPU"
msgid "High performance impact"
msgstr "Tác động cao đến hiệu suất"
msgstr "Ảnh hưởng lớn đến hiệu suất"
msgid "RAM Disk (max. speed)"
msgstr "Đĩa RAM (Tối đa. Tốc đ)"
msgstr "Đĩa RAM (tốc độ tối đa)"
msgid "IBM 8514/A clone (ISA)"
msgstr "IBM 8514/A dòng vô tính (ISA)"
msgstr "IBM 8514/A bản nhái (ISA)"
msgid "Vendor"
msgstr "Nhà sản xuất"

View File

@@ -37,6 +37,7 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message,
return true;
}
if ([event type] == NSEventTypeScrollWheel) {
mouse_set_w(-[event deltaX]);
mouse_set_z([event deltaY]);
return true;
}

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