mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
Merge branch 'master' into pc98x1
This commit is contained in:
@@ -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)
|
||||
|
||||
81
src/86box.c
81
src/86box.c
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
10
src/acpi.c
10
src/acpi.c
@@ -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
@@ -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))) {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
128
src/config.c
128
src/config.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
290
src/cpu/8080.c
290
src/cpu/8080.c
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
186
src/cpu/808x.c
186
src/cpu/808x.c
@@ -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;
|
||||
|
||||
@@ -29,7 +29,7 @@ add_library(cpu OBJECT
|
||||
x86seg_2386.c
|
||||
x87.c
|
||||
x87_timings.c
|
||||
8080.c
|
||||
i8080.c
|
||||
)
|
||||
|
||||
if(AMD_K5)
|
||||
|
||||
305
src/cpu/cpu.c
305
src/cpu/cpu.c
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
826
src/cpu/i8080.c
Normal 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
35
src/cpu/i8080.h
Normal 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_
|
||||
@@ -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*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
281
src/device.c
281
src/device.c
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 } }
|
||||
},
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
154
src/disk/mo.c
154
src/disk/mo.c
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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" }
|
||||
};
|
||||
|
||||
@@ -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" }
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
34
src/include/86box/crc.h
Normal 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*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
158
src/include/86box/qt-glsl.h
Normal 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
|
||||
59
src/include/86box/qt-glslp-parser.h
Normal file
59
src/include/86box/qt-glslp-parser.h
Normal 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_ */
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
16
src/io.c
16
src/io.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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! */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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\"の頂点シェーダのコンパイルエラー。"
|
||||
|
||||
@@ -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 "<html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html>"
|
||||
msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đâ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.</span></p></body></html>"
|
||||
msgstr "<html><head/><body><p>Kết xuất mỗi khung ngay lập tức, đồng bộ với màn hình mô phỏng.</p><p><span style=" font-style:italic;">Đâ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.</span></p></body></html>"
|
||||
|
||||
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 "<html><head/><body><p>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.</p></body></html>"
|
||||
msgstr "<html><head/><body><p>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.</p></body></html>"
|
||||
msgstr "<html><head/><body><p>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.</p></body></html>"
|
||||
|
||||
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 có 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"
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user