Merge branch 'master'
@@ -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)
|
||||
|
||||
79
src/86box.c
@@ -32,6 +32,7 @@
|
||||
#include <wchar.h>
|
||||
#include <stdatomic.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <pwd.h>
|
||||
@@ -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 */
|
||||
@@ -437,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;
|
||||
|
||||
@@ -1086,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);
|
||||
@@ -1216,6 +1293,8 @@ pc_reset_hard_init(void)
|
||||
* modules that are.
|
||||
*/
|
||||
|
||||
keyboard_init();
|
||||
|
||||
/* Reset the IDE and SCSI presences */
|
||||
other_ide_present = other_scsi_present = 0;
|
||||
|
||||
|
||||
@@ -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,7 @@ 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)
|
||||
@@ -256,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()
|
||||
@@ -267,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()
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
@@ -723,7 +723,11 @@ host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/
|
||||
codegen_addlong(block, ram_offset);
|
||||
} else {
|
||||
fatal("host_x86_MOV8_REG_ABS - out of range\n");
|
||||
codegen_alloc_bytes(block, 10);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
|
||||
codegen_addquad(block, (uintptr_t) p);
|
||||
codegen_alloc_bytes(block, 3);
|
||||
codegen_addbyte3(block, 0x41, 0x8a, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/
|
||||
}
|
||||
}
|
||||
void
|
||||
|
||||
37
src/config.c
@@ -192,12 +192,6 @@ load_general(void)
|
||||
else if (mouse_sensitivity > 2.0)
|
||||
mouse_sensitivity = 2.0;
|
||||
|
||||
p = ini_section_get_string(cat, "iconset", NULL);
|
||||
if (p != NULL)
|
||||
strcpy(icon_set, p);
|
||||
else
|
||||
strcpy(icon_set, "");
|
||||
|
||||
enable_discord = !!ini_section_get_int(cat, "enable_discord", 0);
|
||||
|
||||
open_dir_usr_path = ini_section_get_int(cat, "open_dir_usr_path", 0);
|
||||
@@ -2038,11 +2032,6 @@ save_general(void)
|
||||
ini_section_set_string(cat, "language", buffer);
|
||||
}
|
||||
|
||||
if (!strcmp(icon_set, ""))
|
||||
ini_section_delete_var(cat, "iconset");
|
||||
else
|
||||
ini_section_set_string(cat, "iconset", icon_set);
|
||||
|
||||
if (enable_discord)
|
||||
ini_section_set_int(cat, "enable_discord", enable_discord);
|
||||
else
|
||||
@@ -3011,6 +3000,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++) {
|
||||
@@ -3054,6 +3056,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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
302
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;
|
||||
@@ -288,6 +283,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);
|
||||
@@ -383,6 +385,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;
|
||||
@@ -552,6 +562,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
|
||||
@@ -2616,6 +2628,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:
|
||||
@@ -4226,124 +4255,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
@@ -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
@@ -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));
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -113,7 +113,17 @@ static scconvtbl scconv55_8a[18 + 1] =
|
||||
void
|
||||
keyboard_init(void)
|
||||
{
|
||||
num_lock = 0;
|
||||
caps_lock = 0;
|
||||
scroll_lock = 0;
|
||||
shift = 0;
|
||||
|
||||
memset(recv_key, 0x00, sizeof(recv_key));
|
||||
memset(recv_key_ui, 0x00, sizeof(recv_key));
|
||||
memset(oldkey, 0x00, sizeof(recv_key));
|
||||
#if 0
|
||||
memset(key_delay, 0x00, sizeof(recv_key));
|
||||
#endif
|
||||
|
||||
keyboard_scan = 1;
|
||||
scan_table = NULL;
|
||||
|
||||
@@ -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 } }
|
||||
},
|
||||
|
||||
@@ -999,7 +999,8 @@ void
|
||||
serial_standalone_init(void)
|
||||
{
|
||||
while (next_inst < SERIAL_MAX)
|
||||
device_add_inst(&ns8250_device, next_inst + 1);
|
||||
device_add_inst(!strcmp(machine_get_internal_name(), "if386sx") ? &ns16450_device :
|
||||
&ns8250_device, next_inst + 1);
|
||||
};
|
||||
|
||||
const device_t ns8250_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);
|
||||
|
||||
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 },
|
||||
|
||||
@@ -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
|
||||
@@ -113,7 +118,6 @@ extern int vid_resize; /* (C) allow resizing */
|
||||
extern int invert_display; /* (C) invert the display */
|
||||
extern int suppress_overscan; /* (C) suppress overscans */
|
||||
extern uint32_t lang_id; /* (C) language code identifier */
|
||||
extern char icon_set[256]; /* (C) iconset identifier */
|
||||
extern int scale; /* (C) screen scale factor */
|
||||
extern int dpi_scale; /* (C) DPI scaling of the emulated screen */
|
||||
extern int vid_api; /* (C) video renderer */
|
||||
@@ -194,15 +198,12 @@ extern __thread int is_cpu_thread; /* Is this the CPU thread? */
|
||||
#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,24 +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[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;
|
||||
|
||||
/* Needs some extra breathing space in case of overflows. */
|
||||
uint8_t raw_buffer[4096];
|
||||
uint8_t extra_buffer[296];
|
||||
} 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
|
||||
@@ -368,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);
|
||||
@@ -386,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);
|
||||
@@ -398,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);
|
||||
@@ -426,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);
|
||||
|
||||
@@ -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
@@ -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*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
@@ -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,
|
||||
@@ -483,6 +485,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 *);
|
||||
@@ -855,6 +858,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
#ifndef VIDEO_8514A_H
|
||||
#define VIDEO_8514A_H
|
||||
|
||||
#define INT_VSY (1 << 0)
|
||||
#define INT_GE_BSY (1 << 1)
|
||||
#define INT_FIFO_OVR (1 << 2)
|
||||
#define INT_FIFO_EMP (1 << 3)
|
||||
#define INT_MASK 0xf
|
||||
|
||||
typedef struct hwcursor8514_t {
|
||||
int ena;
|
||||
int x;
|
||||
@@ -61,6 +67,7 @@ typedef struct ibm8514_t {
|
||||
uint32_t vram_mask;
|
||||
uint32_t pallook[512];
|
||||
uint32_t bios_addr;
|
||||
uint32_t ma_latch;
|
||||
|
||||
PALETTE vgapal;
|
||||
uint8_t hwcursor_oddeven;
|
||||
@@ -85,8 +92,8 @@ typedef struct ibm8514_t {
|
||||
uint16_t advfunc_cntl;
|
||||
uint16_t cur_y;
|
||||
uint16_t cur_x;
|
||||
int16_t destx;
|
||||
int16_t desty;
|
||||
uint16_t destx;
|
||||
uint16_t desty;
|
||||
int16_t desty_axstp;
|
||||
int16_t destx_distp;
|
||||
int16_t err_term;
|
||||
@@ -117,6 +124,8 @@ typedef struct ibm8514_t {
|
||||
int y1;
|
||||
int y2;
|
||||
int temp_cnt;
|
||||
int16_t dx_ibm;
|
||||
int16_t dy_ibm;
|
||||
int16_t cx;
|
||||
int16_t cx_back;
|
||||
int16_t cy;
|
||||
@@ -216,10 +225,9 @@ typedef struct ibm8514_t {
|
||||
uint16_t subsys_cntl;
|
||||
uint8_t subsys_stat;
|
||||
|
||||
atomic_int fifo_idx;
|
||||
atomic_int ext_fifo_idx;
|
||||
atomic_int force_busy;
|
||||
atomic_int force_busy2;
|
||||
atomic_int fifo_idx;
|
||||
|
||||
int blitter_busy;
|
||||
uint64_t blitter_time;
|
||||
@@ -235,6 +243,11 @@ typedef struct ibm8514_t {
|
||||
PALETTE _8514pal;
|
||||
|
||||
latch8514_t latch;
|
||||
|
||||
void (*vblank_start)(void *priv);
|
||||
void (*accel_out_fifo)(void *priv, uint16_t port, uint16_t val, int len);
|
||||
void (*update_irqs)(void *priv);
|
||||
|
||||
} ibm8514_t;
|
||||
|
||||
#endif /*VIDEO_8514A_H*/
|
||||
|
||||
@@ -25,6 +25,7 @@ typedef struct mach_t {
|
||||
rom_t bios_rom;
|
||||
rom_t bios_rom2;
|
||||
mem_mapping_t mmio_linear_mapping;
|
||||
mem_mapping_t banked_mapping;
|
||||
|
||||
int mca_bus;
|
||||
int pci_bus;
|
||||
@@ -71,7 +72,12 @@ typedef struct mach_t {
|
||||
uint8_t bank_r;
|
||||
uint16_t shadow_set;
|
||||
uint16_t shadow_cntl;
|
||||
int override_resolution;
|
||||
uint8_t overscan_col_8;
|
||||
uint8_t overscan_b_col_24;
|
||||
uint8_t overscan_g_col_24;
|
||||
uint8_t overscan_r_col_24;
|
||||
uint16_t fifo_test_data[17];
|
||||
int resolution_crt;
|
||||
|
||||
struct {
|
||||
uint8_t line_idx;
|
||||
@@ -79,9 +85,9 @@ typedef struct mach_t {
|
||||
uint8_t patt_idx;
|
||||
uint8_t patt_len;
|
||||
uint8_t pix_trans[2];
|
||||
uint8_t eeprom_control;
|
||||
uint8_t alu_bg_fn;
|
||||
uint8_t alu_fg_fn;
|
||||
uint16_t eeprom_control;
|
||||
uint16_t clip_left;
|
||||
uint16_t clip_right;
|
||||
uint16_t clip_top;
|
||||
@@ -92,6 +98,7 @@ typedef struct mach_t {
|
||||
uint16_t src_x_end;
|
||||
uint16_t src_x_start;
|
||||
uint16_t src_x;
|
||||
uint16_t r_src_x;
|
||||
uint16_t src_y;
|
||||
int16_t bres_count;
|
||||
uint16_t clock_sel;
|
||||
@@ -100,6 +107,8 @@ typedef struct mach_t {
|
||||
uint16_t dest_cmp_fn;
|
||||
uint16_t dp_config;
|
||||
uint16_t ext_ge_config;
|
||||
uint16_t crt_offset_lo;
|
||||
uint16_t crt_offset_hi;
|
||||
uint16_t ge_offset_lo;
|
||||
uint16_t ge_offset_hi;
|
||||
uint16_t linedraw_opt;
|
||||
@@ -159,6 +168,7 @@ typedef struct mach_t {
|
||||
} accel;
|
||||
|
||||
atomic_int force_busy;
|
||||
atomic_int fifo_test_idx;
|
||||
} mach_t;
|
||||
|
||||
#endif /*VIDEO_ATI_MACH8_H*/
|
||||
|
||||
@@ -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,8 @@ 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;
|
||||
extern const device_t jvga_device;
|
||||
#endif
|
||||
|
||||
extern int update_overscan;
|
||||
@@ -172,6 +182,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 +210,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*/
|
||||
|
||||
@@ -310,6 +310,11 @@ typedef struct svga_t {
|
||||
void * ext8514;
|
||||
void * clock_gen8514;
|
||||
void * xga;
|
||||
|
||||
/* 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;
|
||||
} svga_t;
|
||||
|
||||
extern void ibm8514_set_poll(svga_t *svga);
|
||||
|
||||
@@ -25,14 +25,19 @@
|
||||
typedef struct vga_t {
|
||||
svga_t svga;
|
||||
|
||||
rom_t bios_rom;
|
||||
rom_t bios_rom;
|
||||
} vga_t;
|
||||
|
||||
extern void vga_out(uint16_t addr, uint8_t val, void *priv);
|
||||
extern void vga_out(uint16_t addr, uint8_t val, void *priv);
|
||||
extern uint8_t vga_in(uint16_t addr, void *priv);
|
||||
|
||||
void vga_disable(void* p);
|
||||
void vga_enable(void* p);
|
||||
int vga_isenabled(void* p);
|
||||
extern void vga_init(const device_t *info, vga_t *vga, int enabled);
|
||||
|
||||
extern void vga_disable(void* p);
|
||||
extern void vga_enable(void* p);
|
||||
|
||||
extern int vga_isenabled(void* p);
|
||||
|
||||
extern video_timings_t timing_vga;
|
||||
|
||||
#endif /*VIDEO_VGA_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
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
@@ -6941,46 +6981,6 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */
|
||||
{
|
||||
.name = "[OPTi 895] Packard Bell PB450",
|
||||
.internal_name = "pb450",
|
||||
.type = MACHINE_TYPE_486_S3_PCI,
|
||||
.chipset = MACHINE_CHIPSET_OPTI_895_802G,
|
||||
.init = machine_at_pb450_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET3,
|
||||
.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_PS2_PCI,
|
||||
.flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.max = 65536,
|
||||
.step = 1024
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = &pb450_device,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */
|
||||
{
|
||||
.name = "[SiS 461] Acer V10",
|
||||
@@ -7875,6 +7875,46 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* has a Phoenix PLCC Multikey copyrighted 1993, version unknown. */
|
||||
{
|
||||
.name = "[OPTi 895] Packard Bell PB450",
|
||||
.internal_name = "pb450",
|
||||
.type = MACHINE_TYPE_486_S3_PCI,
|
||||
.chipset = MACHINE_CHIPSET_OPTI_895_802G,
|
||||
.init = machine_at_pb450_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_SOCKET3,
|
||||
.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_PS2_PCI,
|
||||
.flags = MACHINE_SUPER_IO | MACHINE_IDE_DUAL | MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.max = 65536,
|
||||
.step = 1024
|
||||
},
|
||||
.nvrmask = 255,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = &pb450_device,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* This has an AMIKey-2, which is an updated version of type 'H'. */
|
||||
{
|
||||
.name = "[i420EX] ASUS PVI-486AP4",
|
||||
@@ -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
|
||||
|
||||
@@ -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! */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,9 @@ add_library(ui STATIC
|
||||
qt_openglshaderconfig.hpp
|
||||
qt_openglshaderconfig.cpp
|
||||
qt_openglshaderconfig.ui
|
||||
|
||||
qt_iconindicators.hpp
|
||||
qt_iconindicators.cpp
|
||||
)
|
||||
|
||||
if(RTMIDI)
|
||||
|
||||
BIN
src/qt/icons/active.ico
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
BIN
src/qt/icons/disabled.ico
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |