2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
23 #if defined(__MSDOS__) || defined(MSDOS)
24 static int setup_serial(int sdev);
26 void ser_putchar(int c);
27 void ser_puts(const char *s);
28 void ser_printf(const char *fmt, ...);
33 enum { LOG_FILE, LOG_STREAM, LOG_CON, LOG_CB };
34 enum { LOG_DBG, LOG_INFO, LOG_WARN, LOG_ERR };
37 void (*func)(const char*, void*);
46 struct log_callback cb;
51 static struct log_output outputs[MAX_OUTPUTS];
52 static int num_outputs;
54 void init_logger(void)
59 void cleanup_logger(void)
63 for(i=0; i<num_outputs; i++) {
64 if(outputs[i].type == LOG_FILE) {
65 fclose(outputs[i].out.fp);
71 int add_log_file(const char *fname)
76 if(num_outputs >= MAX_OUTPUTS) {
79 if(!(fp = fopen(fname, "w"))) {
84 outputs[idx].type = LOG_FILE;
85 outputs[idx].out.fp = fp;
89 int add_log_stream(FILE *fp)
93 if(num_outputs >= MAX_OUTPUTS) {
98 outputs[idx].type = LOG_STREAM;
99 outputs[idx].out.fp = fp;
103 int add_log_console(const char *devname)
105 #if defined(MSDOS) || defined(__MSDOS__)
107 if(sscanf(devname, "COM%d", &comport) != 1 || comport < 1 || comport > 2) {
112 if(num_outputs >= MAX_OUTPUTS) {
115 for(i=0; i<num_outputs; i++) {
116 if(outputs[i].type == LOG_CON && outputs[i].out.con == comport) {
120 if(setup_serial(comport) == -1) {
125 outputs[i].type = LOG_CON;
126 outputs[i].out.con = comport;
129 #elif defined(unix) || defined(__unix__)
135 int add_log_callback(void (*cbfunc)(const char*, void*), void *cls)
139 if(num_outputs >= MAX_OUTPUTS) {
144 outputs[idx].type = LOG_CB;
145 outputs[idx].out.cb.func = cbfunc;
146 outputs[idx].out.cb.cls = cls;
150 #if defined(__WATCOMC__)
152 #define vsnprintf _vsnprintf
156 static void logmsg(int type, const char *fmt, va_list ap)
163 while((ret = vsnprintf(buf, bufsz, fmt, ap)) > bufsz || ret < 0) {
167 newsz = bufsz ? bufsz * 2 : 256;
169 if(!(tmp = realloc(buf, newsz))) {
181 for(i=0; i<num_outputs; i++) {
182 switch(outputs[i].type) {
185 fputs(buf, outputs[i].out.fp);
186 fflush(outputs[i].out.fp);
189 #if defined(MSDOS) || defined(__MSDOS__)
195 outputs[i].out.cb.func(buf, outputs[i].out.cb.cls);
204 void errormsg(const char *fmt, ...)
208 logmsg(LOG_ERR, fmt, ap);
212 void warnmsg(const char *fmt, ...)
216 logmsg(LOG_WARN, fmt, ap);
220 void infomsg(const char *fmt, ...)
224 logmsg(LOG_INFO, fmt, ap);
228 void dbgmsg(const char *fmt, ...)
232 logmsg(LOG_DBG, fmt, ap);
236 void verrormsg(const char *fmt, va_list ap)
238 logmsg(LOG_ERR, fmt, ap);
241 void vwarnmsg(const char *fmt, va_list ap)
243 logmsg(LOG_ERR, fmt, ap);
246 void vinfomsg(const char *fmt, va_list ap)
248 logmsg(LOG_ERR, fmt, ap);
251 void vdbgmsg(const char *fmt, va_list ap)
253 logmsg(LOG_ERR, fmt, ap);
257 #if defined(MSDOS) || defined(__MSDOS__)
260 #define UART1_BASE 0x3f8
261 #define UART2_BASE 0x2f8
271 #define DIV_9600 (115200 / 9600)
272 #define DIV_38400 (115200 / 38400)
273 #define LCTL_8N1 0x03
274 #define LCTL_DLAB 0x80
275 #define FIFO_ENABLE_CLEAR 0x07
276 #define MCTL_DTR_RTS_OUT2 0x0b
277 #define LST_TRIG_EMPTY 0x20
279 static unsigned int iobase;
281 static int setup_serial(int sdev)
283 if(sdev < 0 || sdev > 1) {
286 iobase = sdev == 0 ? UART1_BASE : UART2_BASE;
288 /* set clock divisor */
289 outp(iobase | UART_LCTL, LCTL_DLAB);
290 outp(iobase | UART_DIVLO, DIV_9600 & 0xff);
291 outp(iobase | UART_DIVHI, DIV_9600 >> 8);
293 outp(iobase | UART_LCTL, LCTL_8N1);
294 /* assert RTS and DTR */
295 outp(iobase | UART_MCTL, MCTL_DTR_RTS_OUT2);
299 void ser_putchar(int c)
305 while((inp(iobase | UART_LSTAT) & LST_TRIG_EMPTY) == 0);
306 outp(iobase | UART_DATA, c);
309 void ser_puts(const char *s)
316 void ser_printf(const char *fmt, ...)
322 vsprintf(buf, fmt, ap);