aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorgbc dev <gbc@localhost>2026-07-16 00:31:28 +0200
committergbc dev <gbc@localhost>2026-07-16 00:31:28 +0200
commit9158def0bc2db746c6c18312d3b7832addc233f8 (patch)
treea3125fa535d45bb7c876df84af10e5a90750798d /src
parentserial: headless mode tying serial port to stdio for OS debugging (diff)
downloadsl0pboy-9158def0bc2db746c6c18312d3b7832addc233f8.tar.gz
sl0pboy-9158def0bc2db746c6c18312d3b7832addc233f8.tar.xz
sl0pboy-9158def0bc2db746c6c18312d3b7832addc233f8.zip
serial: clean RX path for headless console
- external-clock transfers (SC=$80) deliver a stdin byte into SB without echoing to stdout, and stay pending when no input is available -> programs can poll for input cleanly. internal-clock (SC=$81) stays pure TX.
Diffstat (limited to 'src')
-rw-r--r--src/gb.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/gb.c b/src/gb.c
index 05429fd..7e6771b 100644
--- a/src/gb.c
+++ b/src/gb.c
@@ -117,23 +117,29 @@ void gb_write(GB *gb, u16 addr, u8 val) {
if (addr == 0xFF02) {
gb->sc = val;
if ((val & 0x81) == 0x81) {
- // transfer with internal clock (GB is master): shift out gb->sb,
- // shift in a byte from the peer. Completes instantly.
+ // internal clock (GB is master): transmit gb->sb. Completes now.
u8 outb = gb->sb;
if (gb->serial_log) { fputc(outb, stderr); fflush(stderr); }
if (gb->serial_out_fd >= 0) {
unsigned char c = outb;
(void)!write(gb->serial_out_fd, &c, 1);
}
- // received byte: from serial_in_fd if available, else open-bus 0xFF
- u8 inb = 0xFF;
+ gb->sb = 0xFF; // nothing shifted in on a pure TX
+ gb->sc &= ~0x80;
+ gb_request_interrupt(gb, INT_SERIAL);
+ } else if ((val & 0x81) == 0x80) {
+ // external clock (GB waits for the peer): used as a clean RX path.
+ // Complete only when an input byte is available - and do NOT echo
+ // it to stdout - so a program can poll for input without emitting
+ // junk. Stays pending (bit7 set) while stdin has nothing.
if (gb->serial_in_fd >= 0) {
unsigned char c;
- if (read(gb->serial_in_fd, &c, 1) == 1) inb = c;
+ if (read(gb->serial_in_fd, &c, 1) == 1) {
+ gb->sb = c;
+ gb->sc &= ~0x80;
+ gb_request_interrupt(gb, INT_SERIAL);
+ }
}
- gb->sb = inb;
- gb->sc &= ~0x80;
- gb_request_interrupt(gb, INT_SERIAL);
}
return;
}