From 5cc32ea9cc2fbfca8c9d396006d81023886107c1 Mon Sep 17 00:00:00 2001 From: Terence Boldt Date: Wed, 10 Nov 2021 21:44:28 -0500 Subject: [PATCH] Add partial vt100 emulation to shell (#39) --- Apple2/Shell.asm | 63 +++-- Apple2/Shell.bin | Bin 289 -> 333 bytes Apple2/Shell.lst | 223 ++++++++++-------- RaspberryPi/Apple2-IO-RPi.hdv | Bin 33553920 -> 33553920 bytes .../apple2driver/a2io/communication.go | 1 + RaspberryPi/apple2driver/a2io/gpio.go | 5 + RaspberryPi/apple2driver/a2io/mockio.go | 5 + RaspberryPi/apple2driver/a2io/userio.go | 5 + RaspberryPi/apple2driver/a2io/vt100.go | 182 ++++++++++++++ RaspberryPi/apple2driver/driver.go | 7 + RaspberryPi/apple2driver/handlers/exec.go | 36 +-- 11 files changed, 378 insertions(+), 149 deletions(-) create mode 100644 RaspberryPi/apple2driver/a2io/vt100.go 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 596fc2ab02c62e963f120e48d226c4a68095092f..ae714639dd7a97051ce29c326da382fc9ad5f951 100644 GIT binary patch delta 219 zcmZ3;be73ssd2B5;>snh#w%GBzA7wY*lVMBlHmgzko`j7^GXIFts`(iVS)lo+8IrH zqJw(9k7BEF0#F%P%>ss<3`{3`KX7Q)12vzx@DXeX&;%b11qETn4RS!^bx(SHFgO|Z z!ThB22c?rCA8bxKeQ;2C``2fJf)2w0fg5WX4uEw7%>)W1C`9}LQb5hED!tXLP^PNF W!QZVKAPzrJLJ2CW45TNXi~s=Axm9NX delta 174 zcmX@hw2;YRsd2A@;>snh#w%GBPAV*7*ejrTlHmgzko`j7^GXIFts`(iVS)loS{zM! zqJw&pf?}(20#F%P%>ss<3`{3`KX7Q)12vzx@DXeX&;%b11%>Ad8@PeSOP!qkL0sYO sUmb=60))F!5^y0PBoLiU0rr 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 cef638ef270433faaced9453a39438a085dcc5de..7090cbf6a432a25f59a9280ddc5f2abef6a3e0f4 100755 GIT binary patch delta 2769 zcmZ|PdvuO<0KoC*oi?M3$wZ3YZI&?;8Zb3Wha_dLJf^Lx*E-t)c_tN*Gu5sNco+Yd`` z+^Bi5EeJb^2^tpm?4Fkw{CmXB4njeGC~!9TXW5LB*jA~9MY+9-dKa|mnp^1V>NzY- z4T7QRO%vHK6hADzQ=^y}(_;%J#Vv~q)#}_OFR5}~Syp9icyD-aurfO-5=7$|??~8P z8E|f$P!%o@|1;g~KhqUCIiVI4@{-E3idk5*YId+Zh>1*%#{4Gm7MA73|Eu|2JQ%jAMyDOt%u zN_^sx>x`N&DVevvW@-KSEuooBLbWH?J|~12)WT7SMI4-qM;+9~(KrUj;yBbp0_x*< zG(aL6;si88W1NU4I0+}CDVpIFgpq_~q@X!caVlCM4K2|M>1d4%w83d;i+0FF7TTi& zPDe*{!Wrm{Gm(uhI16VZ2f65qZa4?s(F5nAC(gt9xBz*`$A!2E1-KZ!P>3S*Mj!M= zKU{+TxD*305SQU{6r%)J;7VMDK^TmyF$6;~4A)>dM&MeEL@BPrC|r-xxB)lfCXB&Y z+>CL!1>9zS3^cHl?+grD&XcH&q3hA4L7ckIRHeJkF=4_K=a!ps$&D6Zp?v8qxb4^cko;lxKVDe19xzJo>3e3f(mnk$wrnl*1 z`kH>`64T#YY6h5r<}!1+DK;hM3Uj5o$_z4t&DCaz8ES@^Ys_#n!dz=cno@I}8D*|F zqsWmxW{r8vylvhwYfZ$w zYu+>On{{Tr`M_*2ADWNM$L16Bsrk%&ZZ?`tX0zF1wwf=@m*y+;wfV+;Yqpv1%=hL8 zv)$}4KboJ+&*m4i)BI|FGf}h4{BCxeJ!Y@@!|XGEn*HX0IcTcQA#*siihsY*{^frI Drwm5B delta 2873 zcmZA13v`YJ7{KxO9UCQCLzb9#C3i`5Q$jXWQ;AY^nTqcBq?<@dC7F~jw^~>=MRXw~ zW8bH(R;`;Z(oLa+Aw{|L|F70<=luTPd(QiO&vVYs*+%Z(S7#*VwN36gxOJG;G*}x% zJ|qS8`}WGt$qD}cNy!hwATtbn8&r)=9F*K@V%?fUN2M%C39EJL9Ay^H8r`8VIVz22 z1WQvhOM{9Oo;Rd!FAVr>lUfwzMOCjG{O@(FYuB*(peS>6hg=3Lr}BeEK~m|sikdA) z@b!}Nt(9xok<%iI)<^SdaiC%8)QSetraf(fqSTFZf}+Y%7NqB`$&D6A>3OS|EL~ku z!;j^8yJ7=-hb>}_x`pjynT^AYSeLA@Zm;5~tax(XvXY|e zgOG;0a9@2Kj0Q-@A!vw0(Fl!^fhLHMiNkO>n&JpFLvyr1OSD33v_V@OiFP;&?Qt|Z zpd*gKu{aLL;{`M&cff!o9c;qj5jR-~l{{hcFfoV;mmAc;sOM9>qjFhQ~1p zF+73En1ZR8hUs_`Paz*qV+Lko77FkTp2c%0#B4l|7cd8N@gnA7K3>Ahcm=Ow0T$vl zEW%!3wR^bzTiqG&l zR^tn-!I$_7U*j8mi?#R;-(wxtV*`G`kJyNxunC*71r^weZP<>Vu>-&0SM0 z^fmp=Ip$o`-<)U8Hv`N-bAh?gTx2dbxn_{L#9V4FGlR_#bGf;~TxqT{SDS0hwdOi= zy}7~MXl^n$n_J9KbE_F 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) -}