diff --git a/Apple2/Shell.asm b/Apple2/Shell.asm index 476626f..4b0ab38 100755 --- a/Apple2/Shell.asm +++ b/Apple2/Shell.asm @@ -33,8 +33,11 @@ StringBuffer = $0200 PrintChar = $fded Keyboard = $c000 ClearKeyboard = $c010 +Home = $fc58 Wait = $fca8 PromptChar = $33 +htab = $24 +vtab = $25 ESC = $9b @@ -116,39 +119,53 @@ sendNullTerminator: DumpOutput: jsr GetByte - bcs skipOutput + bcs checkInput cmp #$00 beq endOutput - cmp #ESC - beq escapeSequence + cmp #'H' + beq setColumn + cmp #'V' + beq setRow + cmp #'C' + beq clearScreen + cmp #'T' + beq setTop + cmp #'B' + beq setBottom jsr PrintChar -skipOutput: + jmp DumpOutput +checkInput: bit Keyboard ;check for keypress bpl DumpOutput ;keep dumping output if no keypress lda Keyboard ;send keypress to RPi - ;jsr PrintChar and #$7f jsr SendByte bit ClearKeyboard - clc - bcc DumpOutput + jmp DumpOutput endOutput: rts -escapeSequence: - jsr ParseEscape - clc - bcc DumpOutput - -ParseEscape: - jsr GetByte ; expect first byte after ESC to be '[' - cmp #'['|$80 - beq endParse -checkLetter: - jsr GetByte ; loop until there is a letter - cmp #$C1 - bcc checkLetter -endParse: - rts +clearScreen: + jsr Home + jmp DumpOutput +setColumn: + jsr GetByte + sta htab + sta $057B + jmp DumpOutput +setRow: + jsr GetByte + sta vtab + jsr $fbc1 ; bascalc + sta $28 ;basl + jmp DumpOutput +setTop: + jsr GetByte + sta $22 + jmp DumpOutput +setBottom: + jsr GetByte + sta $23 + jmp DumpOutput SendByte: pha @@ -202,4 +219,4 @@ HelpCommand: PromptCommand: .byte "a2prompt",$00 OldPromptChar: -.byte "]" \ No newline at end of file +.byte "]" diff --git a/Apple2/Shell.bin b/Apple2/Shell.bin index 596fc2a..ae71463 100644 Binary files a/Apple2/Shell.bin and b/Apple2/Shell.bin differ diff --git a/Apple2/Shell.lst b/Apple2/Shell.lst index 93d5801..cbee84a 100644 --- a/Apple2/Shell.lst +++ b/Apple2/Shell.lst @@ -37,47 +37,50 @@ Current file: Shell.asm 000000r 1 PrintChar = $fded 000000r 1 Keyboard = $c000 000000r 1 ClearKeyboard = $c010 +000000r 1 Home = $fc58 000000r 1 Wait = $fca8 000000r 1 PromptChar = $33 +000000r 1 htab = $24 +000000r 1 vtab = $25 000000r 1 000000r 1 ESC = $9b 000000r 1 000000r 1 .org $2000 002000 1 Start: 002000 1 A5 33 lda PromptChar -002002 1 8D 20 21 sta OldPromptChar +002002 1 8D 4C 21 sta OldPromptChar 002005 1 A9 A4 lda #'$'|$80 002007 1 85 33 sta PromptChar 002009 1 A9 05 lda #ExecCommand -00200B 1 20 C9 20 jsr SendByte +00200B 1 20 F5 20 jsr SendByte 00200E 1 A2 00 ldx #$00 002010 1 sendHelpCommand: -002010 1 BD 10 21 lda HelpCommand,x +002010 1 BD 3C 21 lda HelpCommand,x 002013 1 C9 00 cmp #$00 002015 1 F0 06 beq sendHelpCommandEnd -002017 1 20 C9 20 jsr SendByte +002017 1 20 F5 20 jsr SendByte 00201A 1 E8 inx 00201B 1 10 F3 bpl sendHelpCommand 00201D 1 sendHelpCommandEnd: 00201D 1 A9 00 lda #$00 -00201F 1 20 C9 20 jsr SendByte +00201F 1 20 F5 20 jsr SendByte 002022 1 2C 10 C0 bit ClearKeyboard 002025 1 20 90 20 jsr DumpOutput 002028 1 002028 1 Prompt: 002028 1 A9 05 lda #ExecCommand -00202A 1 20 C9 20 jsr SendByte +00202A 1 20 F5 20 jsr SendByte 00202D 1 A2 00 ldx #$00 00202F 1 sendPromptCommand: -00202F 1 BD 17 21 lda PromptCommand,x +00202F 1 BD 43 21 lda PromptCommand,x 002032 1 C9 00 cmp #$00 002034 1 F0 06 beq sendPromptCommandEnd -002036 1 20 C9 20 jsr SendByte +002036 1 20 F5 20 jsr SendByte 002039 1 E8 inx 00203A 1 10 F3 bpl sendPromptCommand 00203C 1 sendPromptCommandEnd: 00203C 1 A9 00 lda #$00 -00203E 1 20 C9 20 jsr SendByte +00203E 1 20 F5 20 jsr SendByte 002041 1 2C 10 C0 bit ClearKeyboard 002044 1 20 90 20 jsr DumpOutput 002047 1 @@ -96,118 +99,132 @@ Current file: Shell.asm 00205F 1 AD 03 02 lda StringBuffer+3 002062 1 C9 F4 cmp #'t'|$80 002064 1 D0 06 bne Execute -002066 1 AD 20 21 lda OldPromptChar +002066 1 AD 4C 21 lda OldPromptChar 002069 1 85 33 sta PromptChar 00206B 1 60 rts 00206C 1 Execute: 00206C 1 2C 10 C0 bit ClearKeyboard 00206F 1 A9 05 lda #ExecCommand -002071 1 20 C9 20 jsr SendByte +002071 1 20 F5 20 jsr SendByte 002074 1 A0 00 ldy #$00 002076 1 sendInput: 002076 1 B9 00 02 lda $0200,y 002079 1 C9 8D cmp #$8d 00207B 1 F0 08 beq sendNullTerminator 00207D 1 29 7F and #$7f -00207F 1 20 C9 20 jsr SendByte +00207F 1 20 F5 20 jsr SendByte 002082 1 C8 iny 002083 1 D0 F1 bne sendInput 002085 1 sendNullTerminator: 002085 1 A9 00 lda #$00 -002087 1 20 C9 20 jsr SendByte +002087 1 20 F5 20 jsr SendByte 00208A 1 20 90 20 jsr DumpOutput 00208D 1 4C 28 20 jmp Prompt 002090 1 002090 1 DumpOutput: -002090 1 20 E7 20 jsr GetByte -002093 1 B0 0B bcs skipOutput +002090 1 20 13 21 jsr GetByte +002093 1 B0 1E bcs checkInput 002095 1 C9 00 cmp #$00 -002097 1 F0 1A beq endOutput -002099 1 C9 9B cmp #ESC -00209B 1 F0 17 beq escapeSequence -00209D 1 20 ED FD jsr PrintChar -0020A0 1 skipOutput: -0020A0 1 2C 00 C0 bit Keyboard ;check for keypress -0020A3 1 10 EB bpl DumpOutput ;keep dumping output if no keypress -0020A5 1 AD 00 C0 lda Keyboard ;send keypress to RPi -0020A8 1 ;jsr PrintChar -0020A8 1 29 7F and #$7f -0020AA 1 20 C9 20 jsr SendByte -0020AD 1 2C 10 C0 bit ClearKeyboard -0020B0 1 18 clc -0020B1 1 90 DD bcc DumpOutput -0020B3 1 endOutput: -0020B3 1 60 rts -0020B4 1 escapeSequence: -0020B4 1 20 BA 20 jsr ParseEscape -0020B7 1 18 clc -0020B8 1 90 D6 bcc DumpOutput -0020BA 1 -0020BA 1 ParseEscape: -0020BA 1 20 E7 20 jsr GetByte ; expect first byte after ESC to be '[' -0020BD 1 C9 DB cmp #'['|$80 -0020BF 1 F0 07 beq endParse -0020C1 1 checkLetter: -0020C1 1 20 E7 20 jsr GetByte ; loop until there is a letter -0020C4 1 C9 C1 cmp #$C1 -0020C6 1 90 F9 bcc checkLetter -0020C8 1 endParse: -0020C8 1 60 rts -0020C9 1 -0020C9 1 SendByte: -0020C9 1 48 pha -0020CA 1 waitWrite: -0020CA 1 AD FB C0 lda InputFlags -0020CD 1 2A rol -0020CE 1 2A rol -0020CF 1 B0 F9 bcs waitWrite -0020D1 1 68 pla -0020D2 1 8D FD C0 sta OutputByte -0020D5 1 A9 1E lda #$1e ; set bit 0 low to indicate write started -0020D7 1 8D F7 C0 sta OutputFlags -0020DA 1 finishWrite: -0020DA 1 AD FB C0 lda InputFlags -0020DD 1 2A rol -0020DE 1 2A rol -0020DF 1 90 F9 bcc finishWrite -0020E1 1 A9 1F lda #$1f -0020E3 1 8D F7 C0 sta OutputFlags -0020E6 1 60 rts -0020E7 1 -0020E7 1 GetByte: -0020E7 1 A9 1D lda #$1d ;set read flag low -0020E9 1 8D F7 C0 sta OutputFlags -0020EC 1 waitRead: -0020EC 1 AD FB C0 lda InputFlags -0020EF 1 2A rol -0020F0 1 90 0C bcc readByte -0020F2 1 2C 00 C0 bit Keyboard ;keypress will abort waiting to read -0020F5 1 10 F5 bpl waitRead -0020F7 1 A9 1F lda #$1f ;set all flags high and exit -0020F9 1 8D F7 C0 sta OutputFlags -0020FC 1 38 sec ;failure -0020FD 1 60 rts -0020FE 1 readByte: -0020FE 1 AD FE C0 lda InputByte -002101 1 48 pha -002102 1 A9 1F lda #$1f ;set all flags high -002104 1 8D F7 C0 sta OutputFlags -002107 1 finishRead: -002107 1 AD FB C0 lda InputFlags +002097 1 F0 2D beq endOutput +002099 1 C9 48 cmp #'H' +00209B 1 F0 30 beq setColumn +00209D 1 C9 56 cmp #'V' +00209F 1 F0 37 beq setRow +0020A1 1 C9 43 cmp #'C' +0020A3 1 F0 22 beq clearScreen +0020A5 1 C9 54 cmp #'T' +0020A7 1 F0 3C beq setTop +0020A9 1 C9 42 cmp #'B' +0020AB 1 F0 40 beq setBottom +0020AD 1 20 ED FD jsr PrintChar +0020B0 1 4C 90 20 jmp DumpOutput +0020B3 1 checkInput: +0020B3 1 2C 00 C0 bit Keyboard ;check for keypress +0020B6 1 10 D8 bpl DumpOutput ;keep dumping output if no keypress +0020B8 1 AD 00 C0 lda Keyboard ;send keypress to RPi +0020BB 1 29 7F and #$7f +0020BD 1 20 F5 20 jsr SendByte +0020C0 1 2C 10 C0 bit ClearKeyboard +0020C3 1 4C 90 20 jmp DumpOutput +0020C6 1 endOutput: +0020C6 1 60 rts +0020C7 1 clearScreen: +0020C7 1 20 58 FC jsr Home +0020CA 1 4C 90 20 jmp DumpOutput +0020CD 1 setColumn: +0020CD 1 20 13 21 jsr GetByte +0020D0 1 85 24 sta htab +0020D2 1 8D 7B 05 sta $057B +0020D5 1 4C 90 20 jmp DumpOutput +0020D8 1 setRow: +0020D8 1 20 13 21 jsr GetByte +0020DB 1 85 25 sta vtab +0020DD 1 20 C1 FB jsr $fbc1 ; bascalc +0020E0 1 85 28 sta $28 ;basl +0020E2 1 4C 90 20 jmp DumpOutput +0020E5 1 setTop: +0020E5 1 20 13 21 jsr GetByte +0020E8 1 85 22 sta $22 +0020EA 1 4C 90 20 jmp DumpOutput +0020ED 1 setBottom: +0020ED 1 20 13 21 jsr GetByte +0020F0 1 85 23 sta $23 +0020F2 1 4C 90 20 jmp DumpOutput +0020F5 1 +0020F5 1 SendByte: +0020F5 1 48 pha +0020F6 1 waitWrite: +0020F6 1 AD FB C0 lda InputFlags +0020F9 1 2A rol +0020FA 1 2A rol +0020FB 1 B0 F9 bcs waitWrite +0020FD 1 68 pla +0020FE 1 8D FD C0 sta OutputByte +002101 1 A9 1E lda #$1e ; set bit 0 low to indicate write started +002103 1 8D F7 C0 sta OutputFlags +002106 1 finishWrite: +002106 1 AD FB C0 lda InputFlags +002109 1 2A rol 00210A 1 2A rol -00210B 1 90 FA bcc finishRead -00210D 1 68 pla -00210E 1 18 clc ;success -00210F 1 end: -00210F 1 60 rts -002110 1 -002110 1 HelpCommand: -002110 1 61 32 68 65 .byte "a2help",$00 -002114 1 6C 70 00 -002117 1 PromptCommand: -002117 1 61 32 70 72 .byte "a2prompt",$00 -00211B 1 6F 6D 70 74 -00211F 1 00 -002120 1 OldPromptChar: -002120 1 5D .byte "]" -002121 1 +00210B 1 90 F9 bcc finishWrite +00210D 1 A9 1F lda #$1f +00210F 1 8D F7 C0 sta OutputFlags +002112 1 60 rts +002113 1 +002113 1 GetByte: +002113 1 A9 1D lda #$1d ;set read flag low +002115 1 8D F7 C0 sta OutputFlags +002118 1 waitRead: +002118 1 AD FB C0 lda InputFlags +00211B 1 2A rol +00211C 1 90 0C bcc readByte +00211E 1 2C 00 C0 bit Keyboard ;keypress will abort waiting to read +002121 1 10 F5 bpl waitRead +002123 1 A9 1F lda #$1f ;set all flags high and exit +002125 1 8D F7 C0 sta OutputFlags +002128 1 38 sec ;failure +002129 1 60 rts +00212A 1 readByte: +00212A 1 AD FE C0 lda InputByte +00212D 1 48 pha +00212E 1 A9 1F lda #$1f ;set all flags high +002130 1 8D F7 C0 sta OutputFlags +002133 1 finishRead: +002133 1 AD FB C0 lda InputFlags +002136 1 2A rol +002137 1 90 FA bcc finishRead +002139 1 68 pla +00213A 1 18 clc ;success +00213B 1 end: +00213B 1 60 rts +00213C 1 +00213C 1 HelpCommand: +00213C 1 61 32 68 65 .byte "a2help",$00 +002140 1 6C 70 00 +002143 1 PromptCommand: +002143 1 61 32 70 72 .byte "a2prompt",$00 +002147 1 6F 6D 70 74 +00214B 1 00 +00214C 1 OldPromptChar: +00214C 1 5D .byte "]" +00214D 1 diff --git a/RaspberryPi/Apple2-IO-RPi.hdv b/RaspberryPi/Apple2-IO-RPi.hdv index cef638e..7090cbf 100755 Binary files a/RaspberryPi/Apple2-IO-RPi.hdv and b/RaspberryPi/Apple2-IO-RPi.hdv differ diff --git a/RaspberryPi/apple2driver/a2io/communication.go b/RaspberryPi/apple2driver/a2io/communication.go index d40b620..1aee7a7 100644 --- a/RaspberryPi/apple2driver/a2io/communication.go +++ b/RaspberryPi/apple2driver/a2io/communication.go @@ -18,4 +18,5 @@ type A2Io interface { ReadByte() (byte, error) ReadString() (string, error) ReadBlock(buffer []byte) error + SendCharacter(character byte) } diff --git a/RaspberryPi/apple2driver/a2io/gpio.go b/RaspberryPi/apple2driver/a2io/gpio.go index f6ccf1d..04c7adb 100644 --- a/RaspberryPi/apple2driver/a2io/gpio.go +++ b/RaspberryPi/apple2driver/a2io/gpio.go @@ -313,3 +313,8 @@ func (a2 A2Gpio) WriteBuffer(buffer []byte) error { return nil } + +// SendCharacter is a pass-through to vt100 implementation +func (a2 A2Gpio) SendCharacter(character byte) { + sendCharacter(a2, character) +} diff --git a/RaspberryPi/apple2driver/a2io/mockio.go b/RaspberryPi/apple2driver/a2io/mockio.go index 1859c5a..04036c1 100644 --- a/RaspberryPi/apple2driver/a2io/mockio.go +++ b/RaspberryPi/apple2driver/a2io/mockio.go @@ -100,3 +100,8 @@ func (mockIo MockIo) ReadBlock(buffer []byte) error { } return mockIo.Data.ErrorToThrow } + +// SendCharacter is a pass-through to vt100 implementation +func (mockIo MockIo) SendCharacter(character byte) { + sendCharacter(mockIo, character) +} diff --git a/RaspberryPi/apple2driver/a2io/userio.go b/RaspberryPi/apple2driver/a2io/userio.go index 476683e..f208393 100644 --- a/RaspberryPi/apple2driver/a2io/userio.go +++ b/RaspberryPi/apple2driver/a2io/userio.go @@ -77,3 +77,8 @@ func (userIo UserIo) ReadBlock(buffer []byte) error { fmt.Printf("ReadBlock: (Not supported)") return errors.New("ReadBlock not supported") } + +// SendCharacter is a pass-through to vt100 implementation +func (userIo UserIo) SendCharacter(character byte) { + sendCharacter(userIo, character) +} diff --git a/RaspberryPi/apple2driver/a2io/vt100.go b/RaspberryPi/apple2driver/a2io/vt100.go new file mode 100644 index 0000000..bb98a4e --- /dev/null +++ b/RaspberryPi/apple2driver/a2io/vt100.go @@ -0,0 +1,182 @@ +// Copyright Terence J. Boldt (c)2021 +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. + +// This file is contains VT100 terminal emulation + +package a2io + +import ( + "fmt" + "time" +) + +var escapeSequence string +var htab, vtab, savedHtab, savedVtab int +var applicationMode bool +var windowTop int +var windowBottom = 22 + +func sendCharacter(comm A2Io, b byte) { + if b == 0x1b { + escapeSequence = "^[" + return + } + if len(escapeSequence) > 0 { + escapeSequence += string(b) + // save cursor + if escapeSequence == "^[7" { + savedHtab = htab + savedVtab = vtab + escapeSequence = "" + } + // restore cursor + if escapeSequence == "^[8" { + htab = savedHtab + vtab = savedVtab + comm.WriteByte('H') + comm.WriteByte(byte(htab)) + comm.WriteByte('V') + comm.WriteByte(byte(vtab)) + escapeSequence = "" + } + if (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') { + switch b { + // Set cursor location + case 'H', 'f': + var ignore string + fmt.Sscanf(escapeSequence, "^[[%d;%d%s", &vtab, &htab, &ignore) + htab-- + vtab-- + comm.WriteByte('H') + comm.WriteByte(byte(htab)) + comm.WriteByte('V') + comm.WriteByte(byte(vtab)) + escapeSequence = "" + case 'r': + fmt.Sscanf(escapeSequence, "^[[%d;%dr", &windowTop, &windowBottom) + windowTop-- + //windowBottom-- + comm.WriteByte('T') + comm.WriteByte(byte(windowTop)) + comm.WriteByte('B') + comm.WriteByte(byte(windowBottom)) + escapeSequence = "" + case 'C': + var right int + fmt.Sscanf(escapeSequence, "^[[%dC", &right) + htab -= right + for i := 0; i < right; i++ { + comm.WriteByte(0x08) + } + escapeSequence = "" + } + switch escapeSequence { + // Set/clear application mode for cursor + case "^[[?1h": + applicationMode = true + comm.WriteByte(0x0c) // ^L clears the screen + escapeSequence = "" + case "^[[?1l": + applicationMode = false + comm.WriteByte('T') + comm.WriteByte(0x00) + comm.WriteByte('B') + comm.WriteByte(0x18) + comm.WriteByte(0x0c) // ^L clears the screen + escapeSequence = "" + // Tab to home position + case "^[[H", "^[[;H", "^[[f", "^[[;f": + htab = 0 + vtab = 0 + comm.WriteByte(0x19) // ^Y moves to home position + escapeSequence = "" + // Clear screen + case "^[[2J", "^[[c": + htab = 0 + vtab = 0 + comm.WriteByte(0x0c) // ^L clears the screen + escapeSequence = "" + // Move down one line + case "^[E": + comm.WriteByte(0x0A) // ^J moves cursor down + escapeSequence = "" + case "^[D": + comm.WriteByte(0x17) // ^W scrolls up + escapeSequence = "" + // Clear line to the right + case "^[[K", "^[[0K": + comm.WriteByte(0x1d) // ^] clears to end of line + escapeSequence = "" + case "^[M": + comm.WriteByte(0x16) // ^V scrolls down + escapeSequence = "" + // Clear screen below cursor + case "^[[J": + comm.WriteByte(0x0b) // ^K clears to end of screen + escapeSequence = "" + case "^[[7m": + comm.WriteByte(0x0f) // ^O inverse video + escapeSequence = "" + case "^[[m", "^[[0m": + comm.WriteByte(0x0e) // ^N normal video + escapeSequence = "" + } + + if len(escapeSequence) > 0 { + fmt.Printf("\nUnhandled escape sequence: %s\n", escapeSequence) + } + escapeSequence = "" + return + } + return + } + fmt.Print(string(b)) + htabIncrement := 0 + switch b { + // convert LF to CR for Apple II compatiblity + case 10: + b = 13 + vtab++ + htab = 0 + htabIncrement = 0 + case 13: + htab = 0 + htabIncrement = 0 + return + // convert TAB to spaces + case 9: + b = ' ' + b |= 0x80 + err := comm.WriteByte(b) + if err != nil { + // try again because could have been cancelled by input + time.Sleep(time.Millisecond * 10) + comm.WriteByte(b) + } + htabIncrement = 2 + default: + htabIncrement = 1 + } + if !applicationMode || htab < 78 { + updateTabs(comm) + b |= 0x80 + htab += htabIncrement + err := comm.WriteByte(b) + if err != nil { + // try again because could have been cancelled by input + time.Sleep(time.Millisecond * 10) + comm.WriteByte(b) + } + } +} + +func updateTabs(comm A2Io) { + if htab >= 80 { + htab = 0 + vtab++ + } + if vtab > windowBottom { + vtab = windowBottom + } +} diff --git a/RaspberryPi/apple2driver/driver.go b/RaspberryPi/apple2driver/driver.go index 9af31c2..a6b4a2d 100644 --- a/RaspberryPi/apple2driver/driver.go +++ b/RaspberryPi/apple2driver/driver.go @@ -12,6 +12,7 @@ import ( "fmt" "os" "path/filepath" + "time" "github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io" "github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/handlers" @@ -36,9 +37,12 @@ func main() { handlers.SetCommunication(comm) comm.Init() + lastCommandTime := time.Now() + for { command, err := comm.ReadByte() if err == nil { + lastCommandTime = time.Now() switch command { case readBlockCommand: handlers.ReadBlockCommand(drive1, drive2) @@ -53,6 +57,9 @@ func main() { case menuCommand: handlers.MenuCommand() } + // temporary workaround for busy wait loop heating up the RPi + } else if time.Since(lastCommandTime) > time.Millisecond*100 { + time.Sleep(time.Millisecond * 100) } } } diff --git a/RaspberryPi/apple2driver/handlers/exec.go b/RaspberryPi/apple2driver/handlers/exec.go index 44559cd..c9aa1ba 100644 --- a/RaspberryPi/apple2driver/handlers/exec.go +++ b/RaspberryPi/apple2driver/handlers/exec.go @@ -75,6 +75,11 @@ func execCommand(linuxCommand string, workingDirectory string) { linuxCommand += " 2>&1" cmd := exec.Command("bash", "-c", linuxCommand) cmd.Dir = workingDirectory + cmd.Env = append(os.Environ(), + "TERM=vt100", + "LINES=24", + "COLUMNS=80", + ) stdout, err := cmd.StdoutPipe() if err != nil { fmt.Printf("Failed to set stdout\n") @@ -100,11 +105,6 @@ func execCommand(linuxCommand string, workingDirectory string) { inputComplete := make(chan bool) userCancelled := make(chan bool) - if linuxCommand == "openssl" { - fmt.Printf("\nSending help command...\n") - io.WriteString(stdin, "help\n") - } - go getStdin(stdin, outputComplete, inputComplete, userCancelled) go getStdout(stdout, outputComplete, userCancelled) @@ -144,7 +144,7 @@ func getStdout(stdout io.ReadCloser, outputComplete chan bool, userCancelled cha } if n > 0 { b := bb[0] - sendCharacter(b) + comm.SendCharacter(b) } } } @@ -160,14 +160,18 @@ func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, use default: b, err := comm.ReadByte() if err == nil { - if b == 3 { + if b == 0x03 { stdin.Close() userCancelled <- true return } - if b == 13 { - b = 10 + if b == 0x0d { + b = 0x0a } + if b == 0x0b { + b = 'k' + } + fmt.Printf("%c", b) io.WriteString(stdin, string(b)) } @@ -220,17 +224,3 @@ func a2wifiSelect(linuxCommand string) (string, error) { "sudo wpa_cli -i wlan0 reconfigure" return linuxCommand, nil } - -func sendCharacter(b byte) { - fmt.Print(string(b)) - if b == 10 { // convert LF to CR for Apple II compatiblity - b = 13 - } - if b == 9 { // convert TAB to spaces - b = ' ' - b += 128 - comm.WriteByte(b) - } - b |= 128 - comm.WriteByte(b) -}