Serial Bodge for X16 Emulator
Forum rules
Post guides, tutorials, and other instructional content here.
This topic area requires approval, so please be patient while we review content to make sure it fits the expectations for this topic area.
Tech support questions should be asked in Hardware or Software support.
Post guides, tutorials, and other instructional content here.
This topic area requires approval, so please be patient while we review content to make sure it fits the expectations for this topic area.
Tech support questions should be asked in Hardware or Software support.
Serial Bodge for X16 Emulator
Purpose communicate between an X16 program running on the official emulator (without modification) and another process running on the host. This allows you to begin developing software for hardware that does not yet exist without modifying or recompiling the emulator.
Implementation A pseudo-serial interface using a pair of chrin/chrout routines that transfer data one byte at a time using LOAD and SAVE on the x16 and read/write on the host side. See unicode terminal for x16 for a practical demonstration. Attached are the 6502 assembly and C implementations used in that program. The 6502 code is likely usable as is, but beware that it saves and restores the .X register using $ff. The C code for the host is likely not usable unless you are making a terminal but it is attached as a reference. It can be modified to use pipes or a socket instead of the posix pseudo terminal interface, or you may wish to write functions that implement matching chrin/chrout functions in your preferred language---the code on the emulator side and the host side do exactly the same thing.
File Format Data is transferred one byte at a time in a 3 byte file. The first two bytes are ignored but are necessary for LOAD & SAVE, the last byte is what is being transferred. A null byte signals that there is no data to be transferred. This means that there is no way to tell the difference between a null byte and no data. This would normally bother me, but it matches the semantics of the commodore chrin. Data transfer is unidirectional. Bidirectional transfer is done using two different files.
Output Data is only written to the output file if the data byte is null. The implementation in serial_chrout continuously reads the file until it gets a null byte, and then overwrites the file with the next data byte. This behaviour means that the routine will block indefinitely if there is not a process reading the data.
Input The input file is read. If the data byte is null then there is not yet any input. The serial_chrin routine will return immediately if there is no input, it will never block. After data has been read in, a null byte is written back to the input file. This is so 1. the process writing the data knows that the next byte can be written and 2. this byte is not read twice by mistake.
emulator_glue.c emu_serial.s