diff --git a/Makefile b/Makefile index 705b090..7b60160 100644 --- a/Makefile +++ b/Makefile @@ -51,12 +51,15 @@ wozmon.bin: wozmon.elf paracli.elf: LDFLAGS += -T doscom.ld paracli.elf: paracli.s paracomm.o -polos.img: fat12boot.bin polmon.com polio.com paracli.com +mushroom.elf: LDFLAGS += -T doscom.ld +mushroom.elf: mushroom.s paracomm.o + +polos.img: fat12boot.bin polmon.com polio.com mushroom.com dd if=/dev/zero of=$@ bs=512 count=720 mformat -i $@ -t 40 -h 2 -s 9 mcopy -i $@ polio.com ::/ mcopy -i $@ polmon.com ::/ - mcopy -i $@ paracli.com ::/ + mcopy -i $@ mushroom.com ::/ dd if=fat12boot.bin of=$@ conv=notrunc .PHONY: clean diff --git a/mrbridge.py b/mrbridge.py new file mode 100644 index 0000000..1ac12b4 --- /dev/null +++ b/mrbridge.py @@ -0,0 +1,55 @@ +import argparse +import serial +import threading +import time +import websocket + + +def parse_args(): + parser = argparse.ArgumentParser(description="Bridge a serial port to a websocket") + parser.add_argument("port", help="path to the serial port") + parser.add_argument("--baudrate", default=115200) + parser.add_argument("--escape", action='store_true') + parser.add_argument("ws", help="URL of the websocket") + return parser.parse_args() + + +def device_thread(device, ws): + while True: + line = device.readline() + ws.send(line) + + +def slowwrite(device, data): + for b in data: + device.write([b]) + time.sleep(0.01) + + +def ws_thread(device, ws): + while True: + data = ws.recv(); + slowwrite(device, data.replace(b'\n', b'\r\n')) + + +def main(): + args = parse_args() + device = serial.Serial(args.port, baudrate=args.baudrate) + ws = websocket.create_connection(args.ws) + + wst = threading.Thread(target=ws_thread, args=(device, ws), daemon=True) + wst.start() + + if args.escape: + device.write([0x03]) + try: + device_thread(device, ws) + except KeyboardInterrupt: + pass + finally: + if args.escape: + device.write([0x02]) + + +if __name__ == "__main__": + main() diff --git a/mushroom.s b/mushroom.s new file mode 100644 index 0000000..48f7448 --- /dev/null +++ b/mushroom.s @@ -0,0 +1,279 @@ + .arch i8086,jumps + .code16 + .intel_syntax noprefix + + .section .init + .global _start +_start: + mov ax, cs + mov ds, ax + mov es, ax + cli + mov ss, ax + mov sp, 0x100 + sti + jmp main + + .section .bss +kBufSize = 77 +kParaDelay = 500 +kDividerRow = 23 + +curpos: .word 0 +inputsize: .byte 0 +escaped: .byte 0 +inputbuf: .zero kBufSize + + # XXX: funky call + # inputs: + # si: string offset + # cl: string length + # clobbers: ax, bh, dx + .section .text.printn +printn: + push bx + push bp + mov bh, 0 +1: + test cl, cl + jz 0f + mov al, [si] + cmpb escaped, 0 + je 3f + cmp al, 'm' + jne 5f + movb escaped, 0 + jmp 5f +3: + cmp al, 0x1b # ESC + jne 4f + movb escaped, 1 + jmp 5f +4: + mov ah, 0x0e # write tty + int 0x10 + push cx + mov ah, 0x03 # get cursor + int 0x10 + cmp dh, kDividerRow + jb 2f + push dx + mov ah, 0x08 # read color + int 0x10 + mov bh, ah + xor cx, cx + mov dx, 0x164f + mov ax, 0x0601 # scroll up, 1 line + int 0x10 + pop dx + dec dh + mov bh, 0 + mov ah, 0x02 # set cursor + int 0x10 +2: + pop cx +5: + inc si + dec cl + jmp 1b +0: + pop bp + pop bx + ret + + # XXX: funky call + # inputs: + # si: string offset + # cl: string length + # clobbers: ax, bh, dx + .section .text.addtext +addtext: + push di + push cx + mov bh, 0 + mov ah, 0x03 # get cursor pos + int 0x10 + pop cx + push dx + mov di, offset curpos + mov dx, [di] + mov ah, 0x02 # set cursor + int 0x10 + call printn + mov ah, 0x03 # get cursor pos + int 0x10 + mov [di], dx + pop dx + mov ah, 0x02 # set cursor + int 0x10 + pop di + ret + + .section .text.paracb +paracb: + push si + mov si, ax + mov cl, dl + call addtext + pop si + ret + + .section .text.sendbuffer +sendbuffer: + push bp + mov bp, sp + sub sp, 2 + mov al, inputsize + mov [bp-2], al + movb inputsize, 0 + mov si, offset .l0 + mov cl, 2 + call addtext + mov si, offset inputbuf + mov cl, [bp-2] + call addtext + mov si, offset .l1 + mov cl, 2 + call addtext + mov si, offset inputbuf + mov cl, [bp-2] + call parasend + # XXX: should check cx in case not everything was sent + mov al, ' ' + mov dx, 0x1802 # [24; 2] + call drawchar + mov ah, 0x02 + int 0x10 # mov cursor back to start of line + add sp, 2 + pop bp + ret + + # draw until end of line + # al: char + # dh: row + # dl: start col + .section .text.drawchar +drawchar: + push ax + mov bh, 0 + mov ah, 0x02 # set cursor + int 0x10 + mov cx, 80 + sub cl, dl + pop ax + mov ah, 0x0a + int 0x10 + ret + + .section .text.parasend +parasend: +1: + test cl, cl + jz 0f + mov al, [si] + push cx + call paracomm_send + pop cx + test al, al + jnz 2f + inc si + dec cl + jmp 1b +0: + mov al, '\n' + call paracomm_send +2: + ret + +prompt: + mov bh, 0 + mov dx, 0x1800 + mov ah, 0x02 + int 0x10 + mov ah, 0x0e + mov al, '>' + int 0x10 + mov ah, 0x0e + mov al, ' ' + int 0x10 + ret + + .section .rodata +.l0: .ascii "> " +.l1: .byte 0x0d, 0x0a +.l2: .ascii "MUSHRoom 8086 client 0.1\r\n" +l2len = . - offset .l2 + + .section .text.main + .global main +main: + movb inputsize, 0 # inputsize = 0 + movw curpos, 0 # mov buffer cursor to [0;0] + movb escaped, 0 + mov ax, 0x0002 + int 0x10 + mov ax, offset paracb + call paracomm_init + mov si, offset .l2 + mov cl, l2len + call addtext + mov dx, 0x1700 # [23; 0] + mov al, 0xc4 # horizontal box line + call drawchar + call prompt +0: + mov ah, 0x01 + int 0x16 # check buffer + jz 1f # if empty, do a round of comms + mov ah, 0x00 + int 0x16 # read 1 key + cmp al, 0x08 # backspace + je 5f + cmp al, 0x0d # CR + je 4f + mov di, offset inputbuf + mov si, offset inputsize + mov bh, 0 + mov bl, [si] + cmp bl, kBufSize # stop accepting input at end of screen + jge 1f # do a round of comms + mov [di+bx], al # store character in buffer + incb [si] # increment buffer size + mov ah, 0x0e + mov bh, 0 + int 0x10 # local echo + jmp 0b +5: + mov bl, inputsize + test bl, bl + jz 0b + decb inputsize + mov bh, 0 + mov ah, 0x0e + int 0x10 # backspace + mov ax, 0x0e20 + int 0x10 + mov ax, 0x0e08 + int 0x10 + jmp 0b +4: + call sendbuffer # send input buffer +1: + call paracomm_nextbyte + mov dx, 0x3bc + out dx, al + add dl, 2 + mov al, 1 + out dx, al + mov cx, kParaDelay +2: loop 2b + mov al, 0 + out dx, al + mov cx, kParaDelay +3: loop 3b + dec dl + in al, dx + mov cl, 4 + shr al, cl + call paracomm_feed + jmp 0b