diff --git a/main.c b/main.c index 20926f84..2aba0d1a 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,7 @@ #include #include "qemm.h" #include "hdpmipt.h" +#include "serial.h" #include #include @@ -221,6 +222,7 @@ struct MAIN_OPT }MAIN_Options[] = { "/?", "Show help", FALSE, 0, + "/DBG", "Debug output (0=console, 1=COM1, 2=COM2)", 0, 0, "/A", "Specify IO address, valid value: 220,240", 0x220, 0, "/I", "Specify IRQ number, valud value: 5,7", 7, 0, "/D", "Specify DMA channel, valid value: 0,1,3", 1, 0, @@ -241,6 +243,8 @@ struct MAIN_OPT enum EOption { OPT_Help, + OPT_DEBUG_OUTPUT, + OPT_ADDR, OPT_IRQ, OPT_DMA, @@ -314,6 +318,19 @@ static void MAIN_SetBlasterEnv(struct MAIN_OPT* opt) //alter BLASTER env. #endif } +static void +update_serial_debug_output() +{ + bool enabled = (MAIN_Options[OPT_DEBUG_OUTPUT].value != 0); + if (!enabled) { + _LOG("Serial port debugging disabled.\n"); + } + ser_setup(MAIN_Options[OPT_DEBUG_OUTPUT].value); + if (enabled) { + _LOG("Serial port debugging enabled.\n"); + } +} + int main(int argc, char* argv[]) { printf("SBEMU: Sound Blaster emulation on AC97. Version: %s", MAIN_SBEMU_VER); @@ -369,6 +386,10 @@ int main(int argc, char* argv[]) } } + if (MAIN_Options[OPT_DEBUG_OUTPUT].value) { + update_serial_debug_output(); + } + if(MAIN_Options[OPT_ADDR].value != 0x220 && MAIN_Options[OPT_ADDR].value != 0x240) { printf("Error: Invalid IO port address: %x.\n", MAIN_Options[OPT_ADDR].value); @@ -1010,6 +1031,13 @@ static void MAIN_TSR_Interrupt() #endif int irq = aui.card_irq; PIC_MaskIRQ(irq); + + if(MAIN_Options[OPT_DEBUG_OUTPUT].value != opt[OPT_DEBUG_OUTPUT].value) + { + MAIN_Options[OPT_DEBUG_OUTPUT].value = opt[OPT_DEBUG_OUTPUT].value; + update_serial_debug_output(); + } + if(MAIN_Options[OPT_OUTPUT].value != opt[OPT_OUTPUT].value || MAIN_Options[OPT_RATE].value != opt[OPT_RATE].value || opt[OPT_RESET].value) { if(opt[OPT_OUTPUT].value != MAIN_Options[OPT_OUTPUT].value || opt[OPT_RESET].value) diff --git a/makefile b/makefile index 6b70fac4..2c63e4ad 100644 --- a/makefile +++ b/makefile @@ -58,6 +58,7 @@ SBEMU_SRC := sbemu/dbopl.cpp \ sbemu/untrapio.c \ sbemu/vdma.c \ sbemu/virq.c \ + sbemu/serial.c \ sbemu/dpmi/xms.c \ sbemu/dpmi/dpmi.c \ sbemu/dpmi/dbgutil.c \ diff --git a/mpxplay/newfunc/newfunc.h b/mpxplay/newfunc/newfunc.h index 5e1204a2..8bb6994b 100644 --- a/mpxplay/newfunc/newfunc.h +++ b/mpxplay/newfunc/newfunc.h @@ -19,6 +19,7 @@ #include #include // for offsetof +#include "serial.h" #ifdef __WATCOMC__ #define NEWFUNC_ASM 1 @@ -1067,6 +1068,11 @@ static void mpxplay_debugf(FILE *fp, const char *format, ...) vsnprintf(sout, 4096, format, ap); va_end(ap); + if (ser_puts(sout)) { + ser_puts("\n"); + return; + } + if(fp){ #ifdef MPXPLAY_EXTENDED_DEBUG mpxplay_debug_create_timestamp(timestamp, sizeof(timestamp)); diff --git a/sbemu/dpmi/dbgutil.c b/sbemu/dpmi/dbgutil.c index a57a0bfb..5086bf86 100644 --- a/sbemu/dpmi/dbgutil.c +++ b/sbemu/dpmi/dbgutil.c @@ -9,6 +9,7 @@ #include #include "dpmi.h" #include "dbgutil.h" +#include "serial.h" #if defined(__BC__) extern BOOL DPMI_IsInProtectedMode(); @@ -129,16 +130,10 @@ void DBG_Logv(const char* fmt, va_list aptr) len = min(len, SIZE-1); buf[len] = '\0'; - #if 0 - outp(0x3F8+3, 0x03); - for(int i = 0; i < len; ++i) - { - while((inp(0x3F8+5)&0x20)==0); - outp(0x3F8, buf[i]); + if (ser_puts(buf)) { + return; } - return; - #endif - + if(!(CPU_FLAGS()&CPU_IFLAG)) { //use VGA when in interrupt VGA_Print(buf); diff --git a/sbemu/serial.c b/sbemu/serial.c new file mode 100644 index 00000000..51023ab4 --- /dev/null +++ b/sbemu/serial.c @@ -0,0 +1,79 @@ +// https://github.com/MindlapseDemos/wip-dosdemo/blob/master/src/dos/logger.c +// GPLv3 by John Tsiombikas + +#include "serial.h" + +#include +#include +#include +#include + +#define UART1_BASE 0x3f8 +#define UART2_BASE 0x2f8 + +#define UART_DATA 0 +#define UART_DIVLO 0 +#define UART_DIVHI 1 +#define UART_FIFO 2 +#define UART_LCTL 3 +#define UART_MCTL 4 +#define UART_LSTAT 5 + +#define DIV_9600 (115200 / 9600) +#define DIV_38400 (115200 / 38400) +#define LCTL_8N1 0x03 +#define LCTL_DLAB 0x80 +#define MCTL_DTR_RTS_OUT2 0x0b +#define LST_TRIG_EMPTY 0x20 + +static unsigned int iobase = 0; + +void +ser_setup(int sdev) +{ + switch (sdev) { + case 1: iobase = UART1_BASE; break; + case 2: iobase = UART2_BASE; break; + default: iobase = 0; break; + } + + if (iobase == 0) { + return; + } + + /* set clock divisor */ + outp(iobase | UART_LCTL, LCTL_DLAB); + outp(iobase | UART_DIVLO, DIV_9600 & 0xff); + outp(iobase | UART_DIVHI, DIV_9600 >> 8); + + /* set format 8n1 */ + outp(iobase | UART_LCTL, LCTL_8N1); + + /* assert RTS and DTR */ + outp(iobase | UART_MCTL, MCTL_DTR_RTS_OUT2); +} + +static void +ser_putchar(int c) +{ + if (c == '\n') { + ser_putchar('\r'); + } + + while((inp(iobase | UART_LSTAT) & LST_TRIG_EMPTY) == 0); + outp(iobase | UART_DATA, c); +} + +bool +ser_puts(const char *s) +{ + if (iobase == 0) { + return false; + } + + while(*s) { + ser_putchar(*s++); + } + + return true; +} diff --git a/sbemu/serial.h b/sbemu/serial.h new file mode 100644 index 00000000..a0398d33 --- /dev/null +++ b/sbemu/serial.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +void +ser_setup(int sdev); + +bool +ser_puts(const char *s);