diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gb.c | 22 |
1 files changed, 14 insertions, 8 deletions
@@ -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; } |
