Why does outp() send strange command characters to the modem with DosBox?

Started by
8 comments, last by yaboiryan 2 years, 8 months ago

I am programming a multiplayer application in DOS so I can get some experience with serial networking programming and I have run into an issue with sending commands to the modem. It is only supposed to send English alphabetical characters, but instead, it sends a group of weird characters, many of which are not even in the English language.

Here is some of my code:

void com_tx(int portnum, unsigned char c)
 {
Uart *p= GetPort(portnum);

if (p->com_installed)
{
    while (!com_tx_ready(portnum)) 
       ;     /* Wait for non-full buffer */
    disable();   // Interrupts off
    p->tx_queue[p->tx_in++] = c;      // Stuff character in queue
    if (p->tx_in == TX_QUEUE_SIZE)
       p->tx_in = 0; // Wrap index if needed
    p->tx_chars++;   // Number of char's in queue 
    // Enable UART tx interrupt 
    outp(p->uart_ier, inp(p->uart_ier) | THRE);
    enable(); // Interrupts back on */
   }
 }

Yes, I know, some of you may find this issue on StackOverflow, but that is because I copied and pasted everything I put on there to gamedev.net because it is kind of early in the morning and I can't type well right now. But still, this is an error I can not quite find the source to…

Here is what the DosBox console window says when I try to send something to the modem:

Modem response:

ERROR Command sent to modem: ->♦(CAZ☻^♦ ♦-CAZ☻^♦♣♦2CAZ☻^♦☺♦7CAZ☻^♥ⁿ♦<CAZ☻^♥≈♦ACAZ☻^♥≥♦FCAZ☻^♥φ♦KCAZ☻^♥Φ♦PCAZ☻^♥π♦UCAZ☻^♥▐♦ZCAZ☻^♥C<-

Thank you all in advance!

Advertisement

Not the same baudrate at both ends?

You seem to be using a memory buffer, but an IO port command. It's been so many years before I looked at these peripherals, but I think that would work as long as the DMA pointers are set up correctly to feed the UART.

Are you sure the DMA buffers/controller is set to read in the same area/order as you write the bytes?

If you write all 0 bytes, or all 0xFF bytes, what do you get out?

If you initialize the buffer with some known pattern (like repeated U characters) before you start writing, do you get a bunch of Us, or something else?

If you initialize the buffer with all U, and then keep poking all U at the UART, but you get something else out, then that's a baud rate problem. If you initialize with all U, and poke something else (like “5”) at the FIFO, and it takes a while to start seeing 5 come out, then it's a DMA/buffer counter mismatch.

enum Bool { True, False, FileNotFound };

@undefined No. I am using 57600 baud rate while on the program I select 28800. Could that be the issue?

@hplus0603 If I hold down the command to send repeated D's (the move forward command for the other player) it sends a bunch of those weird characters. That is actually the output of me doing that.

@undefined and @hplus0603 I just added in increased baud rate support and I get no more success than I did without it. It did not work… There must be something else.

yaboiryan said:
@undefined No. I am using 57600 baud rate while on the program I select 28800. Could that be the issue?

I don't know what DOS box does, but in hardware, the output line first sends a low startbit which is used to synchronize reception, and then it blindly reads 8 values of the input using the supplied baudrate at the other end as timing. So if your bits are sent at a different rate than sampled, you basically get pseudo-random received bit values.

Sending of 0x00 or 0xff as suggested by @hplus0603 can be used as test. Such values keep the line low or high for a longer amount of time so you get a more recognizable result. (With ‘D’ you're sending fluctuating data which seems to be read in some pseudo random manner. By eliminating fluctuation at the sending side you may get more info what happens at the receiving side.) Other potential useful values are a block of 0 bits and then a block of 1 bits, eg 0x1F or 0xC0 or so.

If you didn't already, you may want to figure out serial communication in a separate program. It's easier to debug and experiment then. Once it works you can transplant the result back into the game.

EDIT: Also don't print characters, you want to go down to bit level while bughunting so also print bit strings or hexadecimal values if you can read those as bit sequences. You may want to print those at the sending side as well.

@yaboiryan I proposed a SPECIFIC SET OF THINGS TO TRY to try to debug your program. They were not just random questions, they were intended to make you think about what's actually happening in the system, and start debugging it piece by piece. As Alberth suggests, using data with well defined bit patterns is very helpful here. 0x00 and 0xFF are good, because they're “all low voltage” and “all high voltage” for the duration of the byte. Corruption in memory (sending something else than what you think you're sending) could show up as data that aren't all zeros or all ones. The uppercase U is also good, because it has the hext value 0x55, which means every other bit is high versus low, which means that any mismatch in bit sequencing or baud rate will be detected in seeing some other character.

I suggest you try those, and consider the results.

However, it also sounds like you're not all that clear on how a serial port works in the first place.

When doing low-level DOS development, you're the guy in charge of most parts of the machine. There is much less OS to help you interface with hardware, and there's much less libraries available to help wrap more complex systems into easier helpers. If you don't understand baud rates, or ring buffers, or DMA, or port I/O, then you probably should start by researching those things, and play with them until you understand them, rather than trying to “make a game” on top of that. The “game” bit is just getting in your way. Make sure you understand how to send, and receive, a single character, first – not even with buffering, just send it and wait, and receive it and look at it. If you can get that working, work your way up to buffering. If you can get that working, then consider how you'd want to use that in another program, and build a little library for yourself. Once all THAT works, you might want to try to use that library, which by now should be tested, debugger, and working, to try to build a game.

enum Bool { True, False, FileNotFound };

@hplus0603 I understand. I did some research and I finally got nullmodem working, though I got it working before I did some more research and also before I discovered that nobody is going to go through the trouble of buying a cord just to play multiplayer on a DOS game.

This topic is closed to new replies.

Advertisement