From eb3ab28a813d41a50ea5f967d5b15c28bead22b2 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Tue, 20 Aug 2013 22:10:47 -0400 Subject: [PATCH] initial version (200x) --- ansi.asm | 774 +++++++++++++++++++++++++++++++++++++++ chars.asm | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++ darlene.c | 499 +++++++++++++++++++++++++ display.c | 408 +++++++++++++++++++++ makefile | 23 ++ marinetti.c | 137 +++++++ marinetti.h | 139 +++++++ telnet.h | 83 +++++ vt100.c | 279 ++++++++++++++ 9 files changed, 3342 insertions(+) create mode 100644 ansi.asm create mode 100644 chars.asm create mode 100644 darlene.c create mode 100644 display.c create mode 100644 makefile create mode 100644 marinetti.c create mode 100644 marinetti.h create mode 100644 telnet.h create mode 100644 vt100.c diff --git a/ansi.asm b/ansi.asm new file mode 100644 index 0000000..a7115f7 --- /dev/null +++ b/ansi.asm @@ -0,0 +1,774 @@ + case on + +dummy start + end + +; +;ReverseScrollRegion(line1, line2) +; +ReverseScrollRegion START +line2 equ 9 +line1 equ 7 +_rtlb equ 3 +_d equ 1 + +; brk $ea + + phb + phd + tsc + tcd + + lda 23*8*160 + ldx #$e12000+1920 ; src address + ldy #$e12000+640 ; dest address + +; ldx #$2000+1280 +; ldy #$2000 + + mvn $e10000,$e10000 + +; +; now empty outline #24 +; + pea 23 + jsl ClearLine + + + plb + rtl + + END + +; +; ClearLine(int line_no); clears the line +; +ClearLine START + +line equ 9 +_rtlb equ 5 +tmp equ 3 +_d equ 1 + + +; brk $ea + phb + pha + + phd + tsc + tcd + +; line * 8 * 160 + 4*160 +; = line * 1024 + line * 256 + 4*160 + lda $e10000,x ; stick a 0 in there + txy ; destination address (src + 2) + iny + iny + + + lda #8*160-3 ; length -1 + mvn $e10000,$e10000 + + lda <_rtlb+2 + sta <_rtlb+4 + lda <_rtlb + sta <_rtlb+2 + + pld + pla + pla + plb + rtl + + END + + +;extern void ClearScreenFrom(int Y); +; +; +; +ClearScreenFrom START + +Y equ 9 +_rtlb equ 5 +tmp equ 3 +_d equ 1 + + +; brk $ea + phb + pha + + phd + tsc + tcd + +; line * 8 * 160 + 4*160 +; = line * 1024 + line * 256 + 4*160 + lda $e10000,x ; stick a 0 in there + txy ; destination address (src + 2) + iny + iny + + + phy + lda #$9d00-2 ; end of graphics + $2000 + sec + sbc 1,s + ply + +; a now equals length to clear + + mvn $e10000,$e10000 + + lda <_rtlb+2 + sta <_rtlb+4 + lda <_rtlb + sta <_rtlb+2 + + pld + pla + pla + plb + rtl + + END + +; +;extern void ClearLineFrom(int Y, int X); +; + +; +; clear the end of the line from a given x & y +; +ClearLineFrom START + +X equ 11 +Y equ 9 +_rtlb equ 5 +tmp equ 3 +_d equ 1 + + phb + pha + phd + tsc + tcd + + pea $e1e1 + plb + plb + + +; +; if X is >= 80, skip it... +; + lda $e12000,x + + + + pld + pla ;tmp + pla + sta 5,s + pla + sta 5,s + pla + plb + rtl + + END + + + +; +; clear the screen to black (or whatnot) +; + +ClearScreen START + + phb + pea $e1e1 + plb + plb + lda #0 + ldy #0 +loop anop + sta $2000,y + iny + iny + cpy #32000 + bcc loop + plb + rtl + +; +; this will, in 1 atomic action, blast the screen with 0 +; + + phb + lda #0 + sta >$e12000 + lda #32000-3 ;length + ldx #$2000 + ldy #$2002 + mvn $e10000,$e10000 + + plb + rtl + END +; +; draw a character at the current Xpos & Ypos +; +; + +PrintChar START + +andMask equ 11 +char equ 9 +_rtlb equ 5 +pos equ 3 +_d equ 1 + +; brk $ea + phb + pha + + phd + tsc + tcd + +; sanity check on Xpos && Ypos + lda Xpos + cmp #80 + bcc _ok + lda Ypos + cmp #24 + bcc _ok + brl exit +_ok anop + + + pea $e1e1 + plb + plb + +; +; each line has a width of 160 pixels +; +; start drawing the letter at $e12000 + (Ypos x 160 x 8) + Xpos + + +; 160 * 8 = 1240 = 1024 + 256 + lda >Ypos + and #$00ff + xba ; x 256 + sta Xpos + asl a ; x 2 + clc + adc CHAR_SPACE,x + eor >xor_mask + and CHAR_SPACE+2,x + eor >xor_mask + and CHAR_SPACE+4,x + eor >xor_mask + and CHAR_SPACE+6,x + eor >xor_mask + and CHAR_SPACE+8,x + eor >xor_mask + and CHAR_SPACE+10,x + eor >xor_mask + and CHAR_SPACE+12,x + eor >xor_mask + and CHAR_SPACE+14,x + eor >xor_mask + and + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0000000000000000' + +;? + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000000000000000' + + +;@ + + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011001111000000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + + + +;CHAR_A START + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + + +;CHAR_B START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;CHAR_C START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_D START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;CHAR_E START + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;CHAR_F START + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + +;CHAR_G START + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000011110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;CHAR_H START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_I START + dc b'0000111111000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_J START + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_K START + dc b'0011000011000000' + dc b'0011001100000000' + dc b'0011110000000000' + dc b'0011000000000000' + dc b'0011110000000000' + dc b'0011001100000000' + dc b'0011000011000000' + dc b'0000000000000000' + + +;CHAR_L START + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;CHAR_M START + dc b'0011000000110000' + dc b'0011110011110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_N START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011110000110000' + dc b'0011001100110000' + dc b'0011000011110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_O START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_P START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + + +;CHAR_Q START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011000011000000' + dc b'0000111100110000' + dc b'0000000000000000' + +;CHAR_R START + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011001100000000' + dc b'0011000011000000' + dc b'0011000000110000' + dc b'0000000000000000' +;CHAR_S START + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' +;CHAR_T START + dc b'0011111111110000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;CHAR_U START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;CHAR_V START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000000000000000' + +;CHAR_W START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011110011110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_X START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;CHAR_Y START + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000000000000000' +;CHAR_Z START + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +; _[_ + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +; \ + dc b'0000000000000000' + dc b'0011000000000000' + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000110000' + dc b'0000000000000000' + dc b'0000000000000000' + +; ] + dc b'0011111111110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0011111111110000' + dc b'0000000000000000' + +; ^ + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + +;CHAR__ START + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'1111111111111111' + +; ` + dc b'0000110000000000' + dc b'0000001100000000' + dc b'0000000011000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + + +; a + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;b + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;c + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + +;d + + dc b'0000000000110000' + dc b'0000000000110000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000000000' + +;e + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011111111110000' + dc b'0011000000000000' + dc b'0000111111110000' + dc b'0000000000000000' + +;f + + dc b'0000001111000000' + dc b'0000110000110000' + dc b'0000110000000000' + dc b'0011111111000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000000000000000' + + +; g + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000111111000000' + +;h + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;i + dc b'0000001100000000' + dc b'0000000000000000' + dc b'0000111100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +; j + + dc b'0000000011000000' + dc b'0000000000000000' + dc b'0000001111000000' + dc b'0000000011000000' + dc b'0000000011000000' + dc b'0000000011000000' + dc b'0000110011000000' + dc b'0000001100000000' + +; k + + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000011000000' + dc b'0011001100000000' + dc b'0011111100000000' + dc b'0011000011000000' + dc b'0011000000110000' + dc b'0000000000000000' + +;l + dc b'0000111100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000111111000000' + dc b'0000000000000000' + +;m + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011110011110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011000000110000' + dc b'0000000000000000' + +;n + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000000000000000' + + +;o + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111000000' + dc b'0000000000000000' + +;p + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011111111000000' + dc b'0011000000000000' + dc b'0011000000000000' + +;q + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000000000110000' + +;r + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011001111110000' + dc b'0011110000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0011000000000000' + dc b'0000000000000000' + +;s + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000111111110000' + dc b'0011000000000000' + dc b'0000111111000000' + dc b'0000000000110000' + dc b'0011111111000000' + dc b'0000000000000000' + +;t + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0011111111000000' + dc b'0000110000000000' + dc b'0000110000000000' + dc b'0000110000110000' + dc b'0000001111000000' + dc b'0000000000000000' + +;u + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000011110000' + dc b'0000111100110000' + dc b'0000000000000000' + +;v + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000000000000000' + +; w + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011001100110000' + dc b'0011001100110000' + dc b'0011110011110000' + dc b'0000000000000000' + +;x + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0000110011000000' + dc b'0000001100000000' + dc b'0000110011000000' + dc b'0011000000110000' + dc b'0000000000000000' + +;y + + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0011000000110000' + dc b'0000111111110000' + dc b'0000000000110000' + dc b'0000111111000000' + +;z + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0011111111110000' + dc b'0000000011000000' + dc b'0000001100000000' + dc b'0000110000000000' + dc b'0011111111110000' + dc b'0000000000000000' + +;{ + + dc b'0000001111110000' + dc b'0000111100000000' + dc b'0000111100000000' + dc b'0011110000000000' + dc b'0000111100000000' + dc b'0000111100000000' + dc b'0000001111110000' + dc b'0000000000000000' + + +;| + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + dc b'0000001100000000' + +;} + dc b'0011111100000000' + dc b'0000001111000000' + dc b'0000001111000000' + dc b'0000000011110000' + dc b'0000001111000000' + dc b'0000001111000000' + dc b'0011111100000000' + dc b'0000000000000000' + +;~ + + dc b'0000111100110000' + dc b'0011001111000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + dc b'0000000000000000' + + END + diff --git a/darlene.c b/darlene.c new file mode 100644 index 0000000..d428b65 --- /dev/null +++ b/darlene.c @@ -0,0 +1,499 @@ +#include "Marinetti.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "telnet.h" + +extern void ScrollRegion(word,word); +extern void ScrollDown(void); +extern void PrintChar(int the_char, unsigned int andMask); +extern void ClearScreen(void); +extern void ClearScreenFrom(int Y); +extern void ClearLine(int Y); +extern void ClearLineFrom(int Y, int X); + +extern void GrafOn(void) inline(0x0a04, 0xe10000); +extern void GrafOff(void) inline(0x0b04, 0xe10000); +extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher); +extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); +extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher); +extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher); +extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher); + + +Word MyID; +Word __gno; + +Word modeTelnet = 1; +Word flagEcho = 1; // if *I* echo + + +void init_ansi(void); + +Word ResolveHost(const char *name, cvtRecPtr cvt); +Word GetChar(word ipid, unsigned char *c); +Word UngetChar(char c); + + +void display_str(const char *txt, word cnt); +void display_pstr(const char *); +void display_cstr(const char *); +void display_err(Word); + +void send_event(EventRecord *, Word); + + +#pragma databank 1 + +/* + * called to print connect/disconnect messages from + * Marinetti. msg is a pstring. + */ +void printCallBack(const char *msg) +{ +word i; + i = *msg; + if (i) + { + display_str("\x1b" "[1m", 4); // bold on + display_str(msg + 1, i); // show the string + display_str("\x1b" "[0m\n\r", 6); // bold off + } +} +#pragma databank 0 + +extern word esc; +extern word Xpos; +extern word Ypos; + +void init_screen(void) +{ +#define WHITE 0x0fff +#define YELLOW 0x0ff0 +#define BLACK 0x0000 +#define BLUE 0x000f +#define GREEN 0x00f0 +static ColorTable ct = +{ + 0x0000, //black + 0x00f0, //green 0x5555 + 0x0f00, //blue 0xaaaa + WHITE, //white 0xffff + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE, //white + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE, //white + 0x0000, //black + 0x00f0, //green + 0x0f00, //blue + WHITE //white +}; +int i; + + + // linearize memory, disable shadowing. + asm + { + lda #0x00C1 + sep #0x20 + ora >0xe0c029 + sta >0xe0c029 + rep #0x20 + + lda #0x0008 + sep #0x20 + ora >0xe0c035 + sta >0xe0c035 + rep #0x20 + + } + + SetMasterSCB(0xc080); + SetAllSCBs(0xc080); + InitColorTable(ct); + for (i = 0; i < 15; i++) + SetColorTable(i, ct); + + ClearScreen(); + GrafOn(); +} + + +/* + * this is (more or less) a state machine. + * old state (and character) are passed in + * new state is returned. + * + * 0 = starting state. + */ +#define SB_IAC 0xfaff +Word do_iac(Word state, char c, Word ipid) +{ +static char buffer[64]; +static int cnt; + + if (state == 0) return c == IAC ? IAC : 0; + // FF must be escaped as FF FF within SB. + // SB_IAC means the first FF has been processed. + if (state == SB) + { + if (c == IAC) return SB_IAC; + buffer[cnt++] = c; + return SB; + } + + if (state == SB_IAC) + { + // it was an escped FF + if (c == IAC) + { + buffer[cnt++] = IAC; + return SB; + } + else state = IAC; // process below... + } + if (state == IAC) + switch (c) + { + case DONT: + case DO: + case WONT: + case WILL: + return c; + case SB: + cnt = 0; + return c; + case SE: + // buffer is the data between + // IAC SB <...> IAC SE + if (buffer[0] == TELOPT_TTYPE + && buffer[1] == TELQUAL_SEND) + { + static char msg[] = + { + IAC, SB, TELOPT_TTYPE, TELQUAL_IS, + 'V', 'T', '1', '0', '0', + IAC, SE + }; + TCPIPWriteTCP(ipid, msg, + sizeof(msg) -1, true, false); + } + else if (buffer[0] == TELOPT_NAWS + && buffer[1] == TELQUAL_SEND) + { + static char msg[] = + { + IAC, SB, TELOPT_NAWS, + 0, 80, 0, 24, + IAC, SE + }; + TCPIPWriteTCP(ipid, msg, + sizeof(msg) - 1, true, false); + + } + + cnt = 0; + return 0; + default: + return 0; + } + if (state == DO) + { + buffer[0] = IAC; + buffer[1] = WONT; + buffer[2] = c; + if (c == TELOPT_TTYPE + || c == TELOPT_SGA + || c == TELOPT_NAWS) + { + buffer[1] = WILL; + } + TCPIPWriteTCP(ipid, buffer, 3, true, false); + + } + if (state == DONT) + { + buffer[0] = IAC; + buffer[1] = WONT; + buffer[2] = c; + + TCPIPWriteTCP(ipid, buffer, 3, true, false); + } + if (state == WILL || state == WONT) + { + buffer[0] = IAC; + buffer[1] = DONT; + buffer[2] = c; + if (c == TELOPT_ECHO) + { + buffer[1] = DO; + } + cnt = 3; + + TCPIPWriteTCP(ipid, buffer, cnt, true, false); + } + + return 0; +} + + +int main(int argc, char **argv) +{ +static EventRecord event; +static srBuffer sr; +static rrBuff rr; +static char str[16]; +static cvtRec cvt; +static QuitRecGS qDCB = {2, 0, 0x4000}; + + + Word iLoaded; + Word iConnected; + Word iStarted; + Word Quit; + Word ipid; + Handle dp; + + + int i; + Word key; + Word err; + unsigned char c; + int fd; + int iac_state; + + + Xpos = Ypos = 0; + esc = 0; + //iac = 0; + iLoaded = iStarted = iConnected = false; + __gno = false; + + + MyID = MMStartUp(); + + kernStatus(); + if (!_toolErr) __gno = true; + + TextStartUp(); + SetOutputDevice(1,3); + SetOutGlobals(0x7f, 0); + + + dp = NewHandle(0x0100, MyID, + attrBank | attrPage |attrNoCross | attrFixed | attrLocked, + 0x000000); + HLock(dp); + EMStartUp((Word)*dp, 0x14, 0, 0, 0, 0, MyID); + + + if (argc != 2) + { + ErrWriteCString("Usage: marlene host[:port]\r\n"); + goto _exit; + } + + init_screen(); + + init_ansi(); + + + TCPIPStatus(); + if (_toolErr) + { + display_str("\n\rLoading Marinetti...\n\r", 23); + LoadOneTool(0x36, 0x200); //load Marinetti + if (_toolErr) + { + ErrWriteCString("Unable to load Marinetti\r\n"); + goto _exit; + } + iLoaded = true; + } + + // Marinetti now loaded + if (!TCPIPStatus()) + { + display_str("\n\rStarting Marinetti...\n\r", 24); + TCPIPStartUp(); + iStarted = true; + } + + if (!TCPIPGetConnectStatus()) + { + display_str("\n\rConnecting Marinetti...\n\r", 26); + TCPIPConnect(printCallBack); + if (_toolErr) + { + ErrWriteCString("Unable to establish network connection\r\n"); + goto _exit; + } + iConnected = true; + } + // marinetti is now connected + + if (!ResolveHost(argv[1], &cvt)) + { + ErrWriteCString("Unable to resolve address\r\n"); + goto _exit; + } + + if (!cvt.cvtPort) cvt.cvtPort = 23; + + ipid = TCPIPLogin(MyID, cvt.cvtIPAddress, cvt.cvtPort, 0, 0x0040); + + display_str("\n\rConnecting to ", 16); + display_str(str, TCPIPConvertIPToCAscii(cvt.cvtIPAddress, str, 0)); + + TCPIPOpenTCP(ipid); + + // wait for the connection to occur. + while (1) + { + TCPIPPoll(); + err = TCPIPStatusTCP(ipid, &sr); + if (err) + { + display_err(err); + goto _exit1; + } + + if (sr.srState == tcpsESTABLISHED) break; + //if (sr.srState == tcpsCLOSED) goto _exit1; + GetNextEvent(keyDownMask | autoKeyMask ,&event); + if (event.what != keyDownEvt) continue; + if (!(event.modifiers & appleKey)) continue; + if ((Word)event.message == '.') goto _exit1; + if ((Word)event.message == 'q') goto _exit1; + if ((Word)event.message == 'Q') goto _exit1; + } + + display_str("\n\rConnected\n\r", 13); + + + fd = open ("tcp.log", O_TRUNC | O_WRONLY | O_CREAT, 0777); + + Quit = false; + + + iac_state = 0; + while (!Quit) + { + + TCPIPPoll(); + + // check for incoming data... + // 0xffff = no data + // 0 = data + // otherwise = marinetti error. + err = GetChar(ipid, &c); + + if (err && (err != 0xffff)) + { + display_err(err); + Quit++; + continue; + } + + if (err == 0) + { + if (fd > 0) write(fd, &c, 1); + if (iac_state) + iac_state = do_iac(iac_state, c, ipid); + else if (modeTelnet && c == IAC) + iac_state = do_iac(0, c, ipid); + else display_str(&c, 1); + } + + GetNextEvent(keyDownMask | autoKeyMask, &event); + if (event.what != keyDownEvt) continue; + c = key = event.message; + + if (event.modifiers & appleKey) + { + switch (key) + { + case 'Q': // quit + case 'q': + Quit++; + break; + case 'V': // paste + case 'v': + break; + case 'Z': // suspend (gnome) + case 'z': + if (__gno) + { + static struct sgttyb sb; + static int err; + gtty(1,&sb); + sb.sg_flags &= ~RAW; + stty(1,&sb); + GrafOff(); + Kkill(Kgetpid(), SIGSTOP, &err); + sb.sg_flags |= RAW; + stty(1,&sb); + GrafOn(); + } + break; + } + continue; + + } + else send_event(&event, ipid); + + } + +_exit1: + if (fd > 0) close(fd); + TCPIPCloseTCP(ipid); + TCPIPPoll(); // wait until closed... + TCPIPLogout(ipid); + + // be nice and + while (GetNextEvent(keyDownMask | autoKeyMask, &event)); + display_str("\n\rPress any key to exit.\n\r", 26); + while (!GetNextEvent(keyDownMask | autoKeyMask, &event)); + + +_exit: + + if (iConnected) + TCPIPDisconnect(false, printCallBack); + + if (iStarted) + TCPIPShutDown(); + + if (iLoaded) + UnloadOneTool(0x36); + + + EMShutDown(); + GrafOff(); + TextShutDown(); + QuitGS(&qDCB); + +} + diff --git a/display.c b/display.c new file mode 100644 index 0000000..35964ef --- /dev/null +++ b/display.c @@ -0,0 +1,408 @@ +#pragma noroot +#pragma lint -1 + +#include +#include +#include +#include +#include "Marinetti.h" + +#define ESC "\x1b" + +extern void ScrollRegion(word,word); +extern void ScrollDown(void); +extern void PrintChar(int the_char, unsigned int andMask); +extern void ClearScreen(void); +extern void ClearScreenFrom(int Y); +extern void ClearLine(int Y); +extern void ClearLineFrom(int Y, int X); + +void handle_ansi(word code, char *buffer, word cnt); + +extern void GrafOn(void) inline(0x0a04, 0xe10000); +extern void GrafOff(void) inline(0x0b04, 0xe10000); +extern pascal void SetColorTable(Word, ColorTable) inline(0x0E04,dispatcher); +extern pascal void SysBeep2(Word) inline(0x3803,dispatcher); +extern pascal void SetAllSCBs(Word) inline(0x1404,dispatcher); +extern pascal void SetMasterSCB(Word) inline(0x1604,dispatcher); +extern pascal void InitColorTable(ColorTable) inline(0x0D04,dispatcher); + + + +extern word Xpos; +extern word Ypos; +extern word __scroll[2]; +extern word and_mask; +extern word xor_mask; + +word esc; +char esc_buffer[256]; + +struct errlist +{ + Word Error; + Word MsgLen; + const char *Msg; +}; + +#define _ERR(n,msg) { n, sizeof(msg), msg } + +struct errlist errors[] = +{ + _ERR(1,"tcperrDeafDestPort"), + _ERR(2,"tcperrHostReset"), + _ERR(3,"tcperrConExists"), + _ERR(4,"tcperrConIllegal"), + _ERR(5,"tcperrNoResources"), + _ERR(6,"tcperrNoSocket"), + _ERR(7,"tcperrBadPrec"), + _ERR(8,"tcperrBadSec"), + _ERR(9,"tcperrBadConnection"), + _ERR(0x0a,"tcperrConClosing"), + _ERR(0x0b,"tcperrClosing"), + _ERR(0x0c,"tcperrConReset"), + _ERR(0x0d,"tcperrUserTimeout"), + _ERR(0x0e,"tcperrConRefused"), + + {0,0,NULL} +}; +void display_str(const char *buffer, word cnt); + +void display_err(Word err) +{ +struct errlist *l; + + for (l = &errors[0]; l->Error; l++) + if (l->Error == err) break; + if (l->Error != err) return; + + display_str("\r\n" "\x1b" "[1m", 6); // bold on + display_str(l->Msg, l->MsgLen); // show the string + display_str("\x1b" "[0m", 4); // bold off +} + +void display_cstr(const char *cstr) +{ + if (cstr && *cstr) + display_str(cstr, strlen(cstr)); +} + +void display_pstr(const char *pstr) +{ + if (pstr && *pstr) + display_str(pstr + 1, *pstr); +} + + +void display_char(char c) +{ + switch(c) + { + case 0x07: + SysBeep2(0); + break; + + //backspace + case 0x08: + if (Xpos) Xpos--; + break; + + //tab + case 0x09: + // 1, 9, 17, 25, ... + // not sure this is right + Xpos = Xpos & 0xf8; + Xpos += 8; + //TODO - wrapping + break; + + // line feed + case 0x0A: + if (++Ypos > 23) + { + ScrollRegion(__scroll[0], __scroll[1]); + Ypos = 23; + } + break; + + + case 0x0D: //carriage return + Xpos = 0; + break; + + default: + if (isprint(c)); + { + // check the wrapping flag ... + if (Xpos > 80) + { + Xpos = 0; + if (++Ypos > 23) + { + ScrollRegion(__scroll[0], + __scroll[1]); + + Ypos = 23; + } + } + PrintChar(c, and_mask); + Xpos++; + } + } +} + +/* + * this reads text & has it drawn on the shr screen + * + */ +// todo - and_mask + xor_mask +void display_str(const char *buffer, word cnt) +{ +word i; + + + asm + { + phk + plb + } + + for ( i = 0; i < cnt; i++) + { + if (esc) + { + esc_buffer[esc++] = buffer[i]; + if (isalpha(buffer[i]) + || buffer[i] == '~' + || buffer[i] == '=' + || buffer[i] == '>' + ) + { + handle_ansi(buffer[i], + esc_buffer, esc); + esc = 0; + } + } + else switch (buffer[i]) + { + // bell + case 0x07: + SysBeep2(0); + break; + + //backspace + case 0x08: + if (Xpos) Xpos--; + break; + + //tab + case 0x09: + // 1, 9, 17, 25, ... + // not sure this is right + Xpos = Xpos & 0xf8; + Xpos += 8; + //TODO - wrapping + break; + + // line feed + case 0x0A: + if (++Ypos > 23) + { + ScrollRegion(__scroll[0], + __scroll[1]); + + Ypos = 23; + } + break; + + + case 0x0D: //carriage return + Xpos = 0; + break; + + case 0x1b: //start of escape sequence + + esc = 1; + esc_buffer[0] = 0x1b; + break; + + default: + if (isprint(buffer[i])) + { + // check the wrapping flag ... + if (Xpos > 80) + { + Xpos = 0; + if (++Ypos > 23) + { + ScrollRegion(__scroll[0], + __scroll[1]); + + Ypos = 23; + } + } + PrintChar(buffer[i], and_mask); + Xpos++; + } + } + } +} + +// +// remap the iigs key to a vt100 code (if necessary) and send it out. + +void send_event(EventRecord *event, Word ipid) +{ +char *cp; +int len = 0; +word key; +word mods; + + key = event->message; + mods = event->modifiers; + + + if (mods & keyPad) + { + switch (key) + { + case 0x72: // insert + cp = ESC "[2~"; + len = 4; + break; + + case 0x75: // delete + cp = ESC "[3~"; + len = 4; + break; + + case 0x73: // home + cp = ESC "[1~"; + len = 4; + break; + + case 0x77: // end + cp = ESC "[4~"; + len = 4; + break; + + case 0x74: // page up + cp = ESC "[5~"; + len = 4; + break; + + case 0x79: // page down + cp = ESC "[6~"; + len = 4; + break; + + case 0x7a: // f1 + cp = mods & shiftKey ? ESC "[23~" : ESC "[11~"; + len = 5; + break; + + case 0x78: // f2 + cp = mods & shiftKey ? ESC "[24~" : ESC "[12~"; + len = 5; + break; + + case 0x63: // f3 + cp = mods & shiftKey ? ESC "[25~" : ESC "[13~"; + len = 5; + break; + + case 0x76: // f4 + cp = mods & shiftKey ? ESC "[26~" : ESC "[14~"; + len = 5; + break; + + + case 0x60: // f5 + cp = mods & shiftKey ? ESC "[28~" : ESC "[15~"; + len = 5; + break; + + case 0x61: // f6 + cp = mods & shiftKey ? ESC "[29~" : ESC "[17~"; + len = 5; + break; + + + case 0x62: // f7 + cp = mods & shiftKey ? ESC "[31~" : ESC "[18~"; + len = 5; + break; + + case 0x64: // f8 + cp = mods & shiftKey ? ESC "[32~" : ESC "[19~"; + len = 5; + break; + + case 0x65: // f9 + cp = mods & shiftKey ? ESC "[33~" : ESC "[20~"; + len = 5; + break; + + case 0x6d: // f10 + cp = mods & shiftKey ? ESC "[34~" : ESC "[21~"; + len = 5; + break; + + case 0x67: // f11 + cp = ESC "[23~"; + len = 5; + break; + + case 0x6f: // f12 + cp = ESC "[24~"; + len = 5; + break; + + default: len = 0; cp = NULL; + } + } + else if (mods & controlKey) + { + cp = (char *)&event->message; + len = 1; + } + else + { + switch(key) + { + case 0x0d: + cp = "\r\n"; + len = 2; + break; + case 0x08: // <--- arrow + cp = ESC "[D"; + len = 3; + break; + case 0x0A: // down arrow + cp = ESC "[B"; + len = 3; + break; + case 0x0B: // up arrow + cp = ESC "[A"; + len = 3; + break; + case 0x15: // ---> arrow + cp = ESC "[C"; + len = 3; + break; + + // backspace to delete char + case 0x7f: + cp = "\x08"; + len = 1; + break; + + default: + cp = (char *)&event->message; + len = 1; + } + } + + if (len) TCPIPWriteTCP(ipid, cp, len, false, false); + +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..8a12d0b --- /dev/null +++ b/makefile @@ -0,0 +1,23 @@ +PROG = darlene +OBJS = darlene.o vt100.o ansi.o chars.o marinetti.o display.o + +OPTIMIZE *= 79 + +CFLAGS = -w -O$(OPTIMIZE) + +$(PROG): $(OBJS) + $(RM) ansi.root + $(RM) chars.root + $(CC) $(CFLAGS) $(OBJS) -o $@ + + +darlene.o: darlene.c Marinetti.h +vt100.o: vt100.c +ansi.o: ansi.asm +chars.o: chars.asm +marinetti.o: marinetti.c + +clean: + $(RM) -f *.o *.root *.a *.r +clobber: clean + $(RM) -f $(PROG) diff --git a/marinetti.c b/marinetti.c new file mode 100644 index 0000000..87f67f4 --- /dev/null +++ b/marinetti.c @@ -0,0 +1,137 @@ +#pragma noroot +#pragma lint -1 + +#include +#include "Marinetti.h" + +#include +#include + +static char * __c2pstrMalloc(const char *cp) +{ +Word len; +char *ret; + + len = strlen(cp); + ret = (char *)malloc(len + 2); + + if (ret) + { + ret[0] = len; + memmove(&ret[1], cp, len+1); // copy over NULL too + } + + return ret; +} + +// +// returns true if resolved, false if not +// +// name is a c-string + +// todo - add /etc/host support + +Word ResolveHost(const char *name, cvtRecPtr cvt) +{ +dnrBuffer dnr; +char *pstr; +Word port; +EventRecord event; + + cvt->cvtIPAddress = 0; + cvt->cvtPort = 0; + + if (!name || !*name) return false; + + pstr = __c2pstrMalloc(name); + if (!pstr) return false; + + port = TCPIPMangleDomainName(0xf800, pstr); + + // check if name is a dotted decimal or a host... + + if (TCPIPValidateIPString(pstr)) + { + TCPIPConvertIPToHex(cvt, pstr); + cvt->cvtPort = port; + free (pstr); + return true; + } + else + { + TCPIPDNRNameToIP(pstr, &dnr); + if (_toolErr) + { + free(pstr); + return false; + } + while (dnr.DNRStatus == DNRPending) + { + TCPIPPoll(); + GetNextEvent(keyDownMask | autoKeyMask, &event); + if ((event.what == keyDownEvt) + && (event.modifiers & appleKey) + && ((Word)event.message == '.')) + { + TCPIPCancelDNR(&dnr); + break; + } + } + if (dnr.DNRStatus == DNROK) + { + cvt->cvtIPAddress = dnr.DNRIPAddress; + cvt->cvtPort = port; + free(pstr); + return true; + } + } + + free(pstr); + + return false; +} + + +/* + * pcnt is the next place to store data + * bptr is the current ptr. + */ +static unsigned char buffer[1024]; +static unsigned char pushback[1024]; +static int pcnt = 0; +static int bcnt = 0; +static int bptr = 0; +static rrBuff rr; + +Word GetChar(word ipid, unsigned char *c) +{ +word err; + + *c = 0; + + if (pcnt) + { + *c = pushback[--pcnt]; + return 0; + } + if (!bcnt) + { + err = TCPIPReadTCP(ipid, 0, (Ref)buffer, 1024, &rr); + bcnt = rr.rrBuffCount; + bptr = 0; + if (err) return err; + } + if (bcnt) + { + bcnt--; + *c = buffer[bptr++]; + return 0; + } + return 0xffff; +} + +void UngetChar(char c) +{ + pushback[pcnt++] = c; +} + diff --git a/marinetti.h b/marinetti.h new file mode 100644 index 0000000..cff8387 --- /dev/null +++ b/marinetti.h @@ -0,0 +1,139 @@ +#ifndef __TCPIP_H__ +#define __TCPIP_H__ + +#include + +struct dnrBuffer +{ + Word DNRStatus; + LongWord DNRIPAddress; +}; +typedef struct dnrBuffer dnrBuffer, *dnrBufferPtr, **dnrBufferHndl; + +#define DNRPending 0x0000 +#define DNROK 0x0001 +#define DNRFailed 0x0002 +#define DNRNoDNSEntry 0x0003 +#define DNRCancelled 0x0004 + +struct srBuffer +{ + Word srState; + Word srNetworkError; + LongWord srSndQueued; + LongWord srRcvQueued; + LongWord srDestIP; + Word srDestPort; + Word srConnectType; + Word srAcceptCount; +}; +typedef struct srBuffer srBuffer, *srBufferPtr, **srBufferHndl; + +struct rrBuff +{ + LongWord rrBuffCount; + Handle rrBuffHandle; + Word rrMoreFlag; + Word rrPushFlag; + Word rrUrgentFlag; +}; +typedef struct rrBuff rrBuff, *rrBuffPtr, **rrBuffHndl; + +struct cvtRec +{ + LongWord cvtIPAddress; + Word cvtPort; +}; +typedef struct cvtRec cvtRec, *cvtRecPtr, **cvtRecHndl; + + +/* + * TCP states + */ +#define tcpsCLOSED 0x0000 +#define tcpsLISTEN 0x0001 +#define tcpsSYNSENT 0x0002 +#define tcpsSYNRCVD 0x0003 +#define tcpsESTABLISHED 0x0004 +#define tcpsFINWAIT1 0x0005 +#define tcpsFINWAIT2 0x0006 +#define tcpsCLOSEWAIT 0x0007 +#define tcpsLASTACK 0x0008 +#define tcpsCLOSING 0x0009 +#define tcpsTIMEWAIT 0x000A + + +pascal void TCPIPStartUp(void) + inline(0x0236 ,0xe10000); +pascal void TCPIPShutDown(void) + inline(0x0336 ,0xe10000); + +pascal Word TCPIPStatus(void) + inline(0x0636 ,0xe10000); + +pascal Word TCPIPGetConnectStatus(void) + inline(0x0936, 0xe10000); + + +pascal void TCPIPConvertIPToHex(cvtRecPtr, const char *) + inline(0x0d36 ,0xe10000); +pascal void TCPIPConvertIPCToHex(cvtRecPtr, const char *) + inline(0x3f36 ,0xe10000); + +pascal Word TCPIPConvertIPToAscii(LongWord, const char *, Word) + inline(0x0e36 ,0xe10000); +pascal Word TCPIPConvertIPToCAscii(LongWord, const char *, Word) + inline(0x5836 ,0xe10000); + +pascal Word TCPIPMangleDomainName(Word, char *) + inline(0x5936 ,0xe10000); + +pascal Word TCPIPValidateIPString(const char *) + inline(0x4836 ,0xe10000); +pascal Word TCPIPValidateIPCString(const char *) + inline(0x1536 ,0xe10000); + + + + + +pascal void TCPIPConnect(void *) + inline(0x1236 ,0xe10000); +pascal void TCPIPDisconnect(word, void *) + inline(0x1336 ,0xe10000); + +pascal void TCPIPCancelDNR(dnrBufferPtr) + inline(0x2036 ,0xe10000); +pascal void TCPIPDNRNameToIP(const char *, dnrBufferPtr) + inline(0x2136 ,0xe10000); + +pascal void TCPIPPoll(void) + inline(0x2236 ,0xe10000); + +pascal Word TCPIPLogin(Word, LongWord, Word, Word, Word) + inline(0x2336 ,0xe10000); +pascal void TCPIPLogout(Word) + inline(0x2436 ,0xe10000); + +pascal Word TCPIPOpenTCP(Word) + inline(0x2C36 ,0xe10000); +pascal Word TCPIPWriteTCP(Word, void *, LongWord, Word, Word) + inline(0x2D36 ,0xe10000); +pascal Word TCPIPReadTCP(Word, Word, Ref, LongWord, rrBuffPtr) + inline(0x2E36 ,0xe10000); + + +pascal Word TCPIPCloseTCP(Word) + inline(0x2F36 ,0xe10000); + + +pascal Word TCPIPStatusTCP(Word, srBufferPtr) + inline(0x3136, 0xe10000); + + + + + + +#endif + diff --git a/telnet.h b/telnet.h new file mode 100644 index 0000000..2f65fde --- /dev/null +++ b/telnet.h @@ -0,0 +1,83 @@ +#ifndef __TELNET_H__ +#define __TELNET_H__ + +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 +#define TELOPT_OLD_ENVIRON 36 +#define TELOPT_AUTHENTICATION 37 /* authenticate */ +#define TELOPT_ENCRYPT 38 /* encryption */ +#define TELOPT_NEW_ENVIRON 39 + +#define TELOPT_EXOPL 255 /* extended-options-list */ + +#define TELQUAL_IS 0 +#define TELQUAL_SEND 1 +#define TELQUAL_INFO 2 +#define TELQUAL_REPLY 2 +#define TELQUAL_NAME 3 + + +#endif diff --git a/vt100.c b/vt100.c new file mode 100644 index 0000000..66cf67b --- /dev/null +++ b/vt100.c @@ -0,0 +1,279 @@ +#pragma noroot + +#include +#include +#include +// handle vt100 escape codes + +extern void ReverseScrollRegion(word, word); +extern void ScrollRegion(word, word); +extern void ScrollDown(void); +extern void PrintChar(int the_char, unsigned int andMask); +extern void ClearScreen(void); +extern void ClearScreenFrom(int Y); +extern void ClearLine(int Y); +extern void ClearLineFrom(int Y, int X); + + +word Xpos; +word Ypos; +static word __pos[2]; // saved cursor position +word __scroll[2]; +word and_mask; +word xor_mask; + + +void init_ansi(void) +{ + Xpos = 0; + Ypos = 0; + __pos[0] = 0; + __pos[1] = 0; + __scroll[0] = 0; + __scroll[1] = 23; + and_mask = 0xffff; + xor_mask = 0x0000; +} + +//not yet added: +//esc[6n - return sursor position report +//esc[m - set graphics mode +// + +void dump(const char * buffer, word cnt, int impl) +{ +int i; +char tmp[] = " xx x"; +char c; + + if ( impl) WriteCString("Unimplemented: "); + for (i = 0; i < cnt; i++) + { + c = buffer[i]; + tmp[1] = "0123456789abcdef"[c >> 4]; + tmp[2] = "0123456789abcdef"[c & 0x0f]; + tmp[4] = isprint(c) ? c : '.'; + WriteCString(tmp); + } + WriteCString("\r\n"); +} + + +void handle_ansi(word code, char *buffer, word cnt) +{ +word i; +word r0; +word r1; +//word r2; +//word r3; +word pop = 0; + + + if (buffer[1] == '[') + { + i = 2; + + switch (code) + { + case 'A': //cursor up + // esc[#A + r0 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'A') pop = 1; + else + { + if (!r0) r0 = 1; + Ypos -= r0; + if (Ypos < __scroll[0]) Ypos = __scroll[0]; + //if (Ypos > r0) Ypos -= r0; + //else Ypos = 0; + } + break; + + case 'B': //cursor down + // esc[#B + r0 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'B') pop = 1; + else + { + if (!r0) r0 = 1; + Ypos += r0; + if (Ypos > __scroll[1]) Ypos = __scroll[1]; + //if (Ypos + r0 > 24) Ypos = 24; + //else Ypos += r0; + } + break; + + case 'C': // cursor forward + // esc[#C + r0 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'C') pop = 1; + else + { + if (!r0) r0 = 1; + Xpos += r0; + if (Xpos > 79) Xpos = 79; + } + break; + + case 'D': // cursor backward + // esc[#D + r0 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'D') pop = 1; + else + { + if (!r0) r0 = 1; + Xpos -= r0; + if (Xpos < 0) Xpos = 0; + } + break; + + case 'H': //cursor position + case 'f': + //esc[#;#H or esc[;H or esc[H + //esc[#;#f or esc[;f or esc[f + if (cnt > 3) + { + r0 = r1 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i++] != ';') pop = 1; + else while (isdigit(buffer[i])) + r1 = r1 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'H' && buffer[i] != 'f') pop = 1; + if (r0 == 0) r0++; + if (r1 == 0) r1++; + } + else r0 = r1 = 1; + + if (!pop) + { + Xpos = r1 - 1; + Ypos = r0 - 1; + } + break; + + case 'J': + if (cnt == 3) //clear c + { + ClearLineFrom(Ypos, Xpos); + if (Ypos < 23) + ClearScreenFrom(Ypos+1); + + } + else if (cnt == 4 && buffer[2] == '2') + { + ClearScreen(); + //Ypos = 0; // cursor position unchanged + //Xpos = 0; + } + break; + + case 'K': //erase from cursor to end-of-line (including cursor) + if (cnt == 3) // no parms + ClearLineFrom(Ypos, Xpos); + else dump(buffer, cnt,1); + break; + + case 'L': // erase current line and + // scroll preceding lines down 1 + // esc[#L + ReverseScrollRegion(Ypos, __scroll[1]); + break; + + case 'M': // erase current line and + //scroll following lines up 1 + // esc[#M + ScrollRegion(Ypos, __scroll[1]); + break; + + case 's': // save cursor position + __pos[0] = Xpos; + __pos[1] = Ypos; + break; + + case 'u': // restore cursor position + Xpos = __pos[0]; + Ypos = __pos[1]; + break; + + // not yet added! + case 'n': + break; + case 'm': + while (1) + { + r0 = 0; + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + + switch(r0) + { + case 0: // all attributes off + and_mask = 0xffff; + xor_mask = 0x0000; + break; + case 1: //bold + and_mask = 0xaaaa; + break; + case 4: //underscore + case 5: // blink + and_mask = 0x5555; + break; + case 7://reverse video + xor_mask = 0xffff; + break; + case 8://cancel + and_mask = 0x0000; + break; + } + if (buffer[i] == ';') i++; + else if (buffer[i] == 'm') break; + } + break; + + case 'r': // #;#r == set scrolling region + // esc[#;#r + r0 = r1 = 0; + + while (isdigit(buffer[i])) + r0 = r0 * 10 + (buffer[i++] - '0'); + if (buffer[i++] != ';') pop = 1; + else while (isdigit(buffer[i])) + r1 = r1 * 10 + (buffer[i++] - '0'); + if (buffer[i] != 'r') pop = 1; + if (r0 && r1 && !pop) + { + __scroll[0] = r0 - 1; + __scroll[1] = r1 - 1; + } + break; + + default: + dump(buffer, cnt,1); + } + } + else + { + switch(buffer[1]) + { + case 'M': // scroll screen down 1 line + ReverseScrollRegion(__scroll[0], __scroll[1]); + break; + case '=': // alt key pad + case '>': // normal key pad + break; + default: + dump(buffer, cnt,1); + + } + } +} +