Merge remote-tracking branch 'mainline/master'

This commit is contained in:
starfrost013
2025-01-14 01:33:42 +00:00
15 changed files with 308 additions and 196 deletions

View File

@@ -32,6 +32,7 @@ It is also recommended to use a manager application with 86Box for easier handli
* [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only)
* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia)
* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux)
* [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python)
* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested)
* [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only)

View File

@@ -254,14 +254,9 @@ static volatile atomic_int pause_ack = 0;
#ifndef RELEASE_BUILD
#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 */
#define LOG_SIZE_BUFFER 1024 /* Log size buffer */
static char buff[LOG_SIZE_BUFFER];
static char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER];
static int32_t cyclic_last_line = 0;
static int32_t log_cycles = 0;
static int seen = 0;
@@ -322,112 +317,6 @@ pclog_ex(const char *fmt, va_list ap)
}
/*
Starfrost, 7-8 January 2025:
For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found.
Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
*/
void
pclog_ex_cyclic(const char* fmt, va_list ap)
{
#ifndef RELEASE_BUILD
char temp[LOG_SIZE_BUFFER];
cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES;
vsprintf(temp, fmt, ap);
pclog_ensure_stdlog_open();
strncpy(cyclic_buff[cyclic_last_line], temp, LOG_SIZE_BUFFER);
uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0};
// Random numbers
uint32_t base = 257;
uint32_t mod = 1000000007;
uint32_t repeat_order = 0;
bool is_cycle = false;
// compute the set of hashes for the current log buffer
for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++)
{
if (cyclic_buff[log_line][0] == '\0')
continue; // skip
for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++)
{
hashes[log_line] = hashes[log_line] * base + cyclic_buff[log_line][log_line_char] % mod;
}
}
// Now see if there are real cycles...
// We implement a minimum repeat size.
for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++)
{
//TODO: Log what we need for cycle 1.
//TODO: Command line option that lets us turn off this behaviour.
for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++)
{
if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES])
{
repeat_order = check_size;
break;
}
}
is_cycle = (repeat_order != 0);
// if there still is a cycle..
if (is_cycle)
break;
}
if (is_cycle)
{
if (cyclic_last_line % repeat_order == 0)
{
log_cycles++;
if (log_cycles == 1)
{
// 'Replay' the last few log entries so they actually show up
// Todo: is this right?
for (uint32_t index = cyclic_last_line - 1; index > (cyclic_last_line - repeat_order); index--)
{
// *very important* to prevent out of bounds index
uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES;
fprintf(stdlog, "%s", cyclic_buff[real_index]);
}
fprintf(stdlog, "%s", temp); // allow normal logging
}
if (log_cycles > 1 && log_cycles < 100)
fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log_cycles);
else if (log_cycles == 100)
fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n");
}
}
else
{
log_cycles = 0;
fprintf(stdlog, "%s", temp);
}
cyclic_last_line++;
#endif
}
void
pclog_toggle_suppr(void)

View File

@@ -1634,28 +1634,75 @@ cpu_data_opff_rm(void)
}
}
uint8_t
cpu_inb(uint16_t port)
{
int old_cycles = cycles;
uint8_t ret;
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
ret = inb(port);
resub_cycles(old_cycles);
return ret;
}
uint16_t
cpu_inw(uint16_t port)
{
int old_cycles = cycles;
uint16_t ret;
wait(is_mazovia ? 5 : 4, 1);
if (is8086 && !(port & 1)) {
wait(4, 0);
old_cycles = cycles;
ret = inw(port);
} else {
wait(8, 0);
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
ret = inb(port++);
ret |= (inb(port) << 8);
}
return inw(port);
resub_cycles(old_cycles);
return ret;
}
void
cpu_outb(uint16_t port, uint16_t val)
{
int old_cycles = cycles;
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
outb(port, val);
resub_cycles(old_cycles);
}
void
cpu_outw(uint16_t port, uint16_t val)
{
int old_cycles = cycles;
wait(is_mazovia ? 5 : 4, 1);
if (is8086 && !(port & 1)) {
wait(4, 0);
old_cycles = cycles;
outw(port, val);
} else {
wait(8, 0);
wait(is_mazovia ? 5 : 4, 1);
old_cycles = cycles;
outb(port++, val);
outb(port, val >> 8);
}
return outw(port, val);
resub_cycles(old_cycles);
}
/* Executes instructions up to the specified number of cycles. */
@@ -1804,8 +1851,7 @@ execx86(int cycs)
writememw(es, DI, cpu_inw(DX));
DI += (cpu_state.flags & D_FLAG) ? -2 : 2;
} else {
wait(4, 0);
writememb(es, DI, inb(DX));
writememb(es, DI, cpu_inb(DX));
DI += (cpu_state.flags & D_FLAG) ? -1 : 1;
}
@@ -1833,8 +1879,7 @@ execx86(int cycs)
cpu_outw(DX, readmemw(dest_seg, SI));
SI += (cpu_state.flags & D_FLAG) ? -2 : 2;
} else {
wait(4, 0);
outb(DX, readmemb(dest_seg + SI));
cpu_outb(DX, readmemb(dest_seg + SI));
SI += (cpu_state.flags & D_FLAG) ? -1 : 1;
}
if (in_rep == 0)

View File

@@ -22,12 +22,8 @@ opSYSCALL(uint32_t fetchdat)
ret = syscall_op(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -41,12 +37,8 @@ opSYSRET(uint32_t fetchdat)
ret = sysret(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}

View File

@@ -18,12 +18,8 @@ opSYSENTER(uint32_t fetchdat)
{
int ret = sysenter(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -33,12 +29,8 @@ opSYSEXIT(uint32_t fetchdat)
{
int ret = sysexit(fetchdat);
if (ret <= 1) {
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 7, -1, 0, 0, 0, 0, 0);
PREFETCH_FLUSH();
if (ret <= 1)
CPU_BLOCK_END();
}
return ret;
}
@@ -118,7 +110,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
}
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
CLOCK_CYCLES(1);
} else {
/* FXSAVE */
writememw(easeg, cpu_state.eaaddr, i387_get_control_word());
@@ -163,7 +156,7 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp);
}
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
CLOCK_CYCLES(1);
}
return cpu_state.abrt;
@@ -327,7 +320,8 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
}
}
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
CLOCK_CYCLES(1);
} else {
/* FXSAVE */
if ((twd & 0x0003) != 0x0003)
@@ -372,7 +366,7 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
cpu_state.eaaddr = old_eaaddr;
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
CLOCK_CYCLES(1);
}
return cpu_state.abrt;
@@ -400,8 +394,7 @@ static int
opHINT_NOP_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
CLOCK_CYCLES((is486) ? 1 : 3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
CLOCK_CYCLES(1);
return 0;
}
@@ -409,7 +402,6 @@ static int
opHINT_NOP_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
CLOCK_CYCLES((is486) ? 1 : 3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
CLOCK_CYCLES(1);
return 0;
}

View File

@@ -2127,6 +2127,13 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
pulse_output(dev, val & 0x0f);
dev->state = STATE_MAIN_IBF;
return;
} else if (val == 0xae) {
/* Fast track it because of the LG MultiNet. */
kbc_at_log("ATkbc: enable keyboard\n");
set_enable_kbd(dev, 1);
dev->state = STATE_MAIN_IBF;
return;
}

View File

@@ -448,9 +448,13 @@ static hdd_preset_t hdd_speed_presets[] = {
{ .name = "[ATA-2] Quantum Fireball 640AT", .internal_name = "FB64A341", .model = "QUANTUM FIREBALL 640AT", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3.1, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball TM1080AT", .internal_name = "TM10A462", .model = "QUANTUM FIREBALL TM1.0A", .zones = 2, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball TM1.2AT", .internal_name = "TM12A012", .model = "QUANTUM FIREBALL TM1.2A", .zones = 4, .avg_spt = 120, .heads = 2, .rpm = 4500, .full_stroke_ms = 21, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 8 },
{ .name = "[ATA-2] Quantum Fireball SE8.4A", .internal_name = "SE84A011", .model = "QUANTUM FIREBALL SE8.4A", .zones = 4, .avg_spt = 100, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball SE6.4A", .internal_name = "SE64A011", .model = "QUANTUM FIREBALL SE6.4A", .zones = 3, .avg_spt = 100, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball ST3.2AT", .internal_name = "ST32A461", .model = "QUANTUM FIREBALL ST3.2A", .zones = 4, .avg_spt = 100, .heads = 4, .rpm = 5400, .full_stroke_ms = 21, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 2, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX5.1AT", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball CR4.3AT", .internal_name = "CR43A013", .model = "QUANTUM FIREBALL CR4.3A", .zones = 2, .avg_spt = 110, .heads = 3, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX5.1A", .internal_name = "EX51A012", .model = "QUANTUM FIREBALL EX5.1A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX10.2A", .internal_name = "EX10A011", .model = "QUANTUM FIREBALL EX10.2A", .zones = 3, .avg_spt = 110, .heads = 6, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Quantum Fireball EX12.7A", .internal_name = "EX12A011", .model = "QUANTUM FIREBALL EX12.7A", .zones = 4, .avg_spt = 110, .heads = 8, .rpm = 5400, .full_stroke_ms = 18, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 512, .max_multiple = 16 },
{ .name = "[ATA-2] Samsung PLS-31274A", .internal_name = "PLS31274A", .model = "SAMSUNG PLS-31274A", .zones = 4, .avg_spt = 110, .heads = 4, .rpm = 4500, .full_stroke_ms = 45, .track_seek_ms = 4.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 8 },
{ .name = "[ATA-2] Samsung Winner-1", .internal_name = "WNR31601A", .model = "SAMSUNG WNR-31601A", .zones = 8, .avg_spt = 110, .heads = 4, .rpm = 5400, .full_stroke_ms = 22, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
{ .name = "[ATA-2] Seagate Medalist (ST3780A)", .internal_name = "ST3780A", .model = "ST3780A", .zones = 8, .avg_spt = 120, .heads = 4, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 256, .max_multiple = 16 },

View File

@@ -188,7 +188,6 @@ extern int config_changed; /* config has changed */
/* Function prototypes. */
#ifdef HAVE_STDARG_H
extern void pclog_ex(const char *fmt, va_list ap);
extern void pclog_ex_cyclic(const char* fmt, va_list ap);
extern void fatal_ex(const char *fmt, va_list ap);
#endif
extern void pclog_toggle_suppr(void);

View File

@@ -12,9 +12,11 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Connor Hyde <mario64crashed@gmail.com, nomorestarfrost@gmail.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
* Copyright 2025 Connor Hyde.
*/
#ifndef EMU_LOG_H
@@ -26,11 +28,16 @@
extern "C" {
# 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 */
/* Function prototypes. */
extern void log_set_suppr_seen(void *priv, int suppr_seen);
extern void log_set_dev_name(void *priv, char *dev_name);
# ifdef HAVE_STDARG_H
extern void log_out(void *priv, const char *fmt, va_list);
extern void log_out_cyclic(void* priv, const char *fmt, va_list);
extern void log_fatal(void *priv, const char *fmt, ...);
# endif
extern void *log_open(char *dev_name);

View File

@@ -104,6 +104,7 @@ typedef struct ncr_t {
int state;
int clear_req;
int wait_data;
int wait_data_back;
int wait_complete;
int command_pos;
int data_pos;

167
src/log.c
View File

@@ -12,12 +12,15 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Connor Hyde <mario64crashed@gmail.com, nomorestarfrost@gmail.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
* Copyright 2025 Connor Hyde.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -36,13 +39,31 @@
#ifndef RELEASE_BUILD
typedef struct log_t {
char buff[1024];
char *dev_name;
int seen;
int suppr_seen;
char buff[1024];
char *dev_name;
int seen;
int suppr_seen;
char cyclic_buff[LOG_SIZE_BUFFER_CYCLIC_LINES][LOG_SIZE_BUFFER]; // Cyclical log buffer. This is 32kb, might calloc?
int32_t cyclic_last_line;
int32_t log_cycles;
} log_t;
extern FILE *stdlog; /* file to log output to */
// Functions only used in this translation unit
void log_ensure_stdlog_open(void);
void
log_ensure_stdlog_open(void)
{
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
}
void
log_set_suppr_seen(void *priv, int suppr_seen)
@@ -91,14 +112,7 @@ log_out(void *priv, const char *fmt, va_list ap)
if (strcmp(fmt, "") == 0)
return;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
log_ensure_stdlog_open();
vsprintf(temp, fmt, ap);
if (log->suppr_seen && !strcmp(log->buff, temp))
@@ -117,6 +131,131 @@ log_out(void *priv, const char *fmt, va_list ap)
fflush(stdlog);
}
/*
Starfrost, 7-8 January 2025:
For RIVA 128 emulation I needed a way to suppress logging if a repeated pattern of the same set of lines were found.
Implements a version of the Rabin-Karp algorithm https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm
*/
void
log_out_cyclic(void* priv, const char* fmt, va_list ap)
{
#ifndef RELEASE_BUILD
// get our new logging system instance.
log_t* log = (log_t*)priv;
// does the log actually exist?
if (!log)
return;
// is the string empty?
if (fmt[0] == '\0')
return;
// ensure stdlog is open
log_ensure_stdlog_open();
char temp[LOG_SIZE_BUFFER] = {0};
log->cyclic_last_line %= LOG_SIZE_BUFFER_CYCLIC_LINES;
vsprintf(temp, fmt, ap);
log_copy(log, log->cyclic_buff[log->cyclic_last_line], temp, LOG_SIZE_BUFFER);
uint32_t hashes[LOG_SIZE_BUFFER_CYCLIC_LINES] = {0};
// Random numbers
uint32_t base = 257;
uint32_t mod = 1000000007;
uint32_t repeat_order = 0;
bool is_cycle = false;
// compute the set of hashes for the current log buffer
for (int32_t log_line = 0; log_line < LOG_SIZE_BUFFER_CYCLIC_LINES; log_line++)
{
if (log->cyclic_buff[log_line][0] == '\0')
continue; // skip
for (int32_t log_line_char = 0; log_line_char < LOG_SIZE_BUFFER; log_line_char++)
{
hashes[log_line] = hashes[log_line] * base + log->cyclic_buff[log_line][log_line_char] % mod;
}
}
// Now see if there are real cycles...
// We implement a minimum repeat size.
for (int32_t check_size = LOG_MINIMUM_REPEAT_ORDER; check_size < LOG_SIZE_BUFFER_CYCLIC_LINES / 2; check_size++)
{
//TODO: Log what we need for cycle 1.
//TODO: Command line option that lets us turn off this behaviour.
for (int32_t log_line_to_check = 0; log_line_to_check < check_size; log_line_to_check++)
{
if (hashes[log_line_to_check] == hashes[(log_line_to_check + check_size) % LOG_SIZE_BUFFER_CYCLIC_LINES])
{
repeat_order = check_size;
break;
}
}
is_cycle = (repeat_order != 0);
// if there still is a cycle..
if (is_cycle)
break;
}
if (is_cycle)
{
if (log->cyclic_last_line % repeat_order == 0)
{
log->log_cycles++;
if (log->log_cycles == 1)
{
// 'Replay' the last few log entries so they actually show up
// Todo: is this right?
for (uint32_t index = log->cyclic_last_line - 1; index > (log->cyclic_last_line - repeat_order); index--)
{
// *very important* to prevent out of bounds index
uint32_t real_index = index % LOG_SIZE_BUFFER_CYCLIC_LINES;
log_copy(log, temp, log->cyclic_buff[real_index], LOG_SIZE_BUFFER);
fprintf(stdlog, "%s", log->cyclic_buff[real_index]);
}
// restore the original line
log_copy(log, temp, log->cyclic_buff[log->cyclic_last_line], LOG_SIZE_BUFFER);
fprintf(stdlog, "%s", temp); // allow normal logging
}
if (log->log_cycles > 1 && log->log_cycles < 100)
fprintf(stdlog, "***** Cyclical Log Repeat of Order %d #%d *****\n", repeat_order, log->log_cycles);
else if (log->log_cycles == 100)
fprintf(stdlog, "Logged the same cycle 100 times...shutting up until something interesting happens\n");
}
}
else
{
log->log_cycles = 0;
fprintf(stdlog, "%s", temp);
}
log->cyclic_last_line++;
#endif
}
void
log_fatal(void *priv, const char *fmt, ...)
{
@@ -145,6 +284,8 @@ log_open(char *dev_name)
log->dev_name = dev_name;
log->suppr_seen = 1;
log->cyclic_last_line = 0;
log->log_cycles = 0;
return (void *) log;
}

View File

@@ -58,10 +58,6 @@ machine_at_acerv35n_init(const machine_t *model)
return ret;
machine_at_common_init_ex(model, 2);
/* Yes, it's called amstrad_mega_pc_nvr_device, but it's basically the
standard AT NVR, just initialized to 0x00's (perhaps that should be the
default behavior?). */
device_add(&amstrad_megapc_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);

View File

@@ -17,6 +17,7 @@
* Copyright 2015-2020 Andrew Jenner.
* Copyright 2016-2020 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -496,7 +497,7 @@ pic_read(uint16_t addr, void *priv)
simply read whatever is currently on the data bus. */
}
pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus);
pic_log("pic_read(%04X) = %02X\n", addr, dev->data_bus);
return dev->data_bus;
}

View File

@@ -197,20 +197,30 @@ ncr5380_bus_read(ncr_t *ncr)
phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN);
if (phase == SCSI_PHASE_DATA_IN) {
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->state = STATE_DATAIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) {
ncr5380_log("Phase Data In.\n");
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->state = STATE_DATAIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
}
} else if (phase == SCSI_PHASE_DATA_OUT) {
if (ncr->new_phase & BUS_IDLE) {
ncr->state = STATE_IDLE;
ncr->cur_bus &= ~BUS_BSY;
} else
ncr->state = STATE_DATAOUT;
} else {
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1))
ncr->state = STATE_DATAOUT;
}
} else if (phase == SCSI_PHASE_STATUS) {
ncr5380_log("Phase Status.\n");
ncr->wait_data_back = 0;
ncr->cur_bus |= BUS_REQ;
ncr->state = STATE_STATUS;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_IN) {
ncr5380_log("Phase Message In.\n");
ncr->state = STATE_MESSAGEIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_OUT) {
@@ -335,19 +345,22 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
ncr5380_log("CMD Phase1 DataIn.\n");
scsi_device_command_phase1(dev);
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle in\n");
ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos);
ncr->timer(ncr->priv, ncr->period);
} else {
ncr5380_log("DMA mode IN.\n");
ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos);
ncr->clear_req = 3;
}
@@ -359,7 +372,8 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
case STATE_DATAOUT:
dev = &scsi_devices[ncr->bus][ncr->target_id];
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
@@ -439,12 +453,12 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
switch (port & 7) {
case 0: /* Output data register */
ncr5380_log("Write: Output data register, val = %02x\n", val);
ncr5380_log("[%04X:%08X]: Write: Output data register, val=%02x\n", CS, cpu_state.pc, val);
ncr->output_data = val;
break;
case 1: /* Initiator Command Register */
ncr5380_log("Write: Initiator command register\n");
ncr5380_log("[%04X:%08X]: Write: Initiator command register, val=%02x.\n", CS, cpu_state.pc, val);
if ((val & 0x80) && !(ncr->icr & 0x80)) {
ncr5380_log("Resetting the 5380\n");
ncr5380_reset(ncr);
@@ -465,7 +479,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 3: /* Target Command Register */
ncr5380_log("Write: Target Command register\n");
ncr5380_log("Write: Target Command register, val=%02x.\n", val);
ncr->tcr = val;
break;
@@ -482,7 +496,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 7: /* start DMA Initiator Receive */
ncr5380_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA);
ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA);
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
if (ncr->dma_initiator_receive_ext)
@@ -510,13 +524,13 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
ncr5380_log("Read: Current SCSI data register\n");
if (ncr->icr & ICR_DBP) {
/*Return the data from the output register if on data bus phase from ICR*/
ncr5380_log("Data Bus Phase, ret = %02x\n", ncr->output_data);
ret = ncr->output_data;
ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data);
} else {
/*Return the data from the SCSI bus*/
ncr5380_bus_read(ncr);
ncr5380_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus));
ret = BUS_GETDATA(ncr->cur_bus);
ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret);
}
break;
@@ -595,7 +609,9 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
break;
case 6:
ret = ncr->tx_data;
ncr5380_log("Read: Input Data.\n");
ncr5380_bus_read(ncr);
ret = BUS_GETDATA(ncr->cur_bus);
break;
case 7: /* reset Parity/Interrupt */

View File

@@ -148,6 +148,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
ncr400->busy = 1;
if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0)))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
break;
@@ -181,13 +187,15 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
memset(ncr400->buffer, 0, MIN(128, dev->buffer_length));
if (ncr->mode & MODE_MONITOR_BUSY)
timer_on_auto(&ncr400->timer, ncr->period);
timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0);
else if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 40.0);
else
timer_on_auto(&ncr400->timer, ncr->period);
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
ncr->wait_data_back = ncr->wait_data;
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n",
ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
}
break;
@@ -244,6 +252,12 @@ ncr53c400_read(uint32_t addr, void *priv)
ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl);
if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
break;
@@ -397,16 +411,20 @@ t130b_in(uint16_t port, void *priv)
}
static void
ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv))
ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
{
ncr_t *ncr = (ncr_t *) priv;
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
if (!(ncr->mode & MODE_DMA)) {
ncr53c400_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded);
if (!ncr400->block_count_loaded) {
if (!(ncr->mode & MODE_DMA)) {
ncr53c400_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
}
}
}
@@ -474,6 +492,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -527,6 +546,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
@@ -544,6 +564,7 @@ ncr53c400_callback(void *priv)
break;
}
ncr53c400_log("Bus Read.\n");
ncr5380_bus_read(ncr);
if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {